summaryrefslogtreecommitdiffstats
path: root/toolkit/components/feeds
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/feeds')
-rw-r--r--toolkit/components/feeds/FeedProcessor.js1792
-rw-r--r--toolkit/components/feeds/FeedProcessor.manifest14
-rw-r--r--toolkit/components/feeds/moz.build31
-rw-r--r--toolkit/components/feeds/nsIFeed.idl86
-rw-r--r--toolkit/components/feeds/nsIFeedContainer.idl85
-rw-r--r--toolkit/components/feeds/nsIFeedElementBase.idl28
-rw-r--r--toolkit/components/feeds/nsIFeedEntry.idl46
-rw-r--r--toolkit/components/feeds/nsIFeedGenerator.idl30
-rw-r--r--toolkit/components/feeds/nsIFeedListener.idl87
-rw-r--r--toolkit/components/feeds/nsIFeedPerson.idl30
-rw-r--r--toolkit/components/feeds/nsIFeedProcessor.idl57
-rw-r--r--toolkit/components/feeds/nsIFeedResult.idl65
-rw-r--r--toolkit/components/feeds/nsIFeedTextConstruct.idl57
-rw-r--r--toolkit/components/feeds/test/.eslintrc.js8
-rw-r--r--toolkit/components/feeds/test/chrome.ini3
-rw-r--r--toolkit/components/feeds/test/head.js80
-rw-r--r--toolkit/components/feeds/test/test_bug675492.xul31
-rw-r--r--toolkit/components/feeds/test/test_xml.js97
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/author_namespaces.xml16
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_author.xml30
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_content.xml35
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_content_encoded.xml43
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_content_html.xml35
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_content_xhtml.xml39
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_content_xhtml_with_markup.xml39
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_contributor.xml30
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_html_cdata.xml28
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_id.xml35
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_link_2alts.xml27
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_link_2alts_allcore.xml28
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_link_2alts_allcore2.xml33
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_link_IANA.xml29
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_link_alt_extension.xml25
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_link_enclosure.xml27
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_link_enclosure_populate_enclosures.xml27
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_link_otherURI_alt.xml25
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_link_payment_alt.xml27
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_link_random.xml28
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_published.xml28
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_rights_normalized.xml17
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_summary.xml40
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_title.xml35
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_title_normalized.xml35
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_updated.xml27
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_w_content_encoded.xml43
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_xhtml_baseURI_with_amp.xml37
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_xmlBase.xml21
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/entry_xmlBase_on_link.xml22
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_atom_rights_xhtml.xml18
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_author.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_author2.xml14
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_author_email.xml14
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_author_email_2.xml18
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_author_name.xml13
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_author_surrounded.xml27
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_author_uri.xml20
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_comment_rss_extra_att.xml29
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_contributor.xml20
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_entry_count.xml14
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_generator.xml33
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_generator_uri.xml33
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_generator_uri_xmlbase.xml33
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_generator_version.xml33
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_icon.xml11
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_id.xml27
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_id_extra_att.xml28
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_logo.xml11
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_random_attributes_on_feed_and_entry.xml30
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_rights_normalized.xml15
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_rights_xhtml.xml15
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_rights_xhtml_nested_divs.xml15
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_subtitle.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_tantek_title.xml46
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_title.xml10
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_title_full_feed.xml936
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_title_xhtml.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_title_xhtml_entities.xml14
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_updated.xml27
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_updated_invalid.xml27
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_updated_normalized.xml27
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_version.xml9
-rw-r--r--toolkit/components/feeds/test/xml/rfc4287/feed_xmlBase.xml23
-rw-r--r--toolkit/components/feeds/test/xml/rss09x/rss090.xml50
-rw-r--r--toolkit/components/feeds/test/xml/rss09x/rss091.xml28
-rw-r--r--toolkit/components/feeds/test/xml/rss09x/rss091_withNS.xml28
-rw-r--r--toolkit/components/feeds/test/xml/rss09x/rss092.xml27
-rw-r--r--toolkit/components/feeds/test/xml/rss09x/rss093.xml27
-rw-r--r--toolkit/components/feeds/test/xml/rss09x/rss094.xml27
-rw-r--r--toolkit/components/feeds/test/xml/rss09x/rssUnknown.xml27
-rw-r--r--toolkit/components/feeds/test/xml/rss1/feed_bogus_title.xml45
-rw-r--r--toolkit/components/feeds/test/xml/rss1/feed_description.xml17
-rw-r--r--toolkit/components/feeds/test/xml/rss1/feed_description_normalized.xml17
-rw-r--r--toolkit/components/feeds/test/xml/rss1/feed_description_with_dc.xml19
-rw-r--r--toolkit/components/feeds/test/xml/rss1/feed_description_with_dc_only.xml17
-rw-r--r--toolkit/components/feeds/test/xml/rss1/feed_generator.xml34
-rw-r--r--toolkit/components/feeds/test/xml/rss1/feed_id.xml25
-rw-r--r--toolkit/components/feeds/test/xml/rss1/feed_image.xml39
-rw-r--r--toolkit/components/feeds/test/xml/rss1/feed_items_length_zero.xml17
-rw-r--r--toolkit/components/feeds/test/xml/rss1/feed_link.xml16
-rw-r--r--toolkit/components/feeds/test/xml/rss1/feed_link_normalized.xml16
-rw-r--r--toolkit/components/feeds/test/xml/rss1/feed_textInput.xml40
-rw-r--r--toolkit/components/feeds/test/xml/rss1/feed_title.xml15
-rw-r--r--toolkit/components/feeds/test/xml/rss1/feed_title_extra_att.xml16
-rw-r--r--toolkit/components/feeds/test/xml/rss1/feed_title_normalized.xml15
-rw-r--r--toolkit/components/feeds/test/xml/rss1/feed_updated.xml26
-rw-r--r--toolkit/components/feeds/test/xml/rss1/feed_updated_dctermsmodified.xml27
-rw-r--r--toolkit/components/feeds/test/xml/rss1/feed_version.xml14
-rw-r--r--toolkit/components/feeds/test/xml/rss1/full_feed.xml41
-rw-r--r--toolkit/components/feeds/test/xml/rss1/full_feed_not_bozo.xml354
-rw-r--r--toolkit/components/feeds/test/xml/rss1/full_feed_unknown_extension.xml55
-rw-r--r--toolkit/components/feeds/test/xml/rss1/item_2_dc_description.xml34
-rw-r--r--toolkit/components/feeds/test/xml/rss1/item_2_dc_publisher.xml35
-rw-r--r--toolkit/components/feeds/test/xml/rss1/item_2_dc_publisher_extra_att_invalid_rdf.xml36
-rw-r--r--toolkit/components/feeds/test/xml/rss1/item_count.xml32
-rw-r--r--toolkit/components/feeds/test/xml/rss1/item_dc_creator.xml34
-rw-r--r--toolkit/components/feeds/test/xml/rss1/item_dc_description.xml35
-rw-r--r--toolkit/components/feeds/test/xml/rss1/item_dc_description_normalized.xml37
-rw-r--r--toolkit/components/feeds/test/xml/rss1/item_description.xml31
-rw-r--r--toolkit/components/feeds/test/xml/rss1/item_id.xml32
-rw-r--r--toolkit/components/feeds/test/xml/rss1/item_link.xml32
-rw-r--r--toolkit/components/feeds/test/xml/rss1/item_link_normalized.xml32
-rw-r--r--toolkit/components/feeds/test/xml/rss1/item_title.xml31
-rw-r--r--toolkit/components/feeds/test/xml/rss1/item_title_normalized.xml32
-rw-r--r--toolkit/components/feeds/test/xml/rss1/item_updated_dcterms.xml28
-rw-r--r--toolkit/components/feeds/test/xml/rss1/item_wiki_importance_extra_att.xml34
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_category.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_category_count.xml15
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_cloud.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_copyright.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_copyright_linebreak.xml15
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_data_outside_channel.xml13
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_dc_contributor.xml14
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_dc_creator.xml13
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_description.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_description_html.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_description_html_cdata.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_docs.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_generator.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_image_desc.xml17
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_image_desc_width_height.xml19
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_image_required.xml16
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_language.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_lastBuildDate.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_linebreak_link.xml14
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_link.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_link_cdata.xml14
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_managingEditor.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_managingEditor_extra_att.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_multiple_categories.xml15
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_pubDate.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_pubDate_invalid.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_pubDate_nonRFC822_1.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_pubDate_nonRFC822_2.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_pubDate_timezoneZ.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_pubDate_utc.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_rating.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_single_quote_stylesheet_pi.xml26
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_skipDays.xml15
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_skipHours.xml18
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_subtitle.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_subtitle_html.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_subtitle_markup_stripped.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_textinput.xml17
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_title.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_title_cdata_mixed.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_title_nesting.xml13
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_ttl.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_updated.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_updated_dcdate.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_updated_lastBuildDate.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_updated_lastBuildDate_priority.xml13
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_webMaster.xml12
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_wfw_commentapi.xml15
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_wfw_commentrss.xml15
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_wiki.xml18
-rw-r--r--toolkit/components/feeds/test/xml/rss2/feed_wiki_unusual_prefix.xml18
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_author.xml15
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_category.xml16
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_comments.xml19
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_content_encoded.xml15
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_count.xml26
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_count2.xml30
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_description.xml18
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_description_2.xml21
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_description_cdata.xml20
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_description_decode_entities.xml21
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_description_normalized.xml18
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_description_normalized_nohtml.xml18
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_enclosure.xml21
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_enclosure_duplicates.xml24
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_enclosure_duplicates2.xml24
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_enclosure_mixed.xml33
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_enclosure_mixed2.xml33
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_guid.xml21
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_guid_bogus_url.xml21
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink.xml20
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_default.xml20
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false.xml20
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false_uppercase.xml20
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_true_uppercase.xml20
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_unknown_value.xml20
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_guid_normalized.xml21
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_guid_with_link.xml22
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_link.xml19
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_link_normalized.xml19
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_plain_desc.xml19
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_populated_enclosures.xml21
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_pubDate.xml14
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_published.xml14
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_title.xml14
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_title_normalized.xml14
-rw-r--r--toolkit/components/feeds/test/xml/rss2/item_updated_dcdate.xml14
-rw-r--r--toolkit/components/feeds/test/xml/rss2/items_2_titles.xml17
-rw-r--r--toolkit/components/feeds/test/xml/rss2/mrss_content.xml21
-rw-r--r--toolkit/components/feeds/test/xml/rss2/mrss_content2.xml22
-rw-r--r--toolkit/components/feeds/test/xml/rss2/mrss_content_429049.xml32
-rw-r--r--toolkit/components/feeds/test/xml/rss2/mrss_content_multiple.xml23
-rw-r--r--toolkit/components/feeds/test/xml/rss2/mrss_content_populate_enclosure.xml21
-rw-r--r--toolkit/components/feeds/test/xml/rss2/mrss_group_content.xml26
-rw-r--r--toolkit/components/feeds/test/xml/rss2/mrss_group_content_populate_enclosure.xml26
-rw-r--r--toolkit/components/feeds/test/xpcshell.ini209
221 files changed, 8553 insertions, 0 deletions
diff --git a/toolkit/components/feeds/FeedProcessor.js b/toolkit/components/feeds/FeedProcessor.js
new file mode 100644
index 000000000..88d0ad6ed
--- /dev/null
+++ b/toolkit/components/feeds/FeedProcessor.js
@@ -0,0 +1,1792 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* 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/. */
+
+function LOG(str) {
+ dump("*** " + str + "\n");
+}
+
+const Ci = Components.interfaces;
+const Cc = Components.classes;
+const Cr = Components.results;
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+const FP_CONTRACTID = "@mozilla.org/feed-processor;1";
+const FP_CLASSID = Components.ID("{26acb1f0-28fc-43bc-867a-a46aabc85dd4}");
+const FP_CLASSNAME = "Feed Processor";
+const FR_CONTRACTID = "@mozilla.org/feed-result;1";
+const FR_CLASSID = Components.ID("{072a5c3d-30c6-4f07-b87f-9f63d51403f2}");
+const FR_CLASSNAME = "Feed Result";
+const FEED_CONTRACTID = "@mozilla.org/feed;1";
+const FEED_CLASSID = Components.ID("{5d0cfa97-69dd-4e5e-ac84-f253162e8f9a}");
+const FEED_CLASSNAME = "Feed";
+const ENTRY_CONTRACTID = "@mozilla.org/feed-entry;1";
+const ENTRY_CLASSID = Components.ID("{8e4444ff-8e99-4bdd-aa7f-fb3c1c77319f}");
+const ENTRY_CLASSNAME = "Feed Entry";
+const TEXTCONSTRUCT_CONTRACTID = "@mozilla.org/feed-textconstruct;1";
+const TEXTCONSTRUCT_CLASSID =
+ Components.ID("{b992ddcd-3899-4320-9909-924b3e72c922}");
+const TEXTCONSTRUCT_CLASSNAME = "Feed Text Construct";
+const GENERATOR_CONTRACTID = "@mozilla.org/feed-generator;1";
+const GENERATOR_CLASSID =
+ Components.ID("{414af362-9ad8-4296-898e-62247f25a20e}");
+const GENERATOR_CLASSNAME = "Feed Generator";
+const PERSON_CONTRACTID = "@mozilla.org/feed-person;1";
+const PERSON_CLASSID = Components.ID("{95c963b7-20b2-11db-92f6-001422106990}");
+const PERSON_CLASSNAME = "Feed Person";
+
+const IO_CONTRACTID = "@mozilla.org/network/io-service;1"
+const BAG_CONTRACTID = "@mozilla.org/hash-property-bag;1"
+const ARRAY_CONTRACTID = "@mozilla.org/array;1";
+const SAX_CONTRACTID = "@mozilla.org/saxparser/xmlreader;1";
+const PARSERUTILS_CONTRACTID = "@mozilla.org/parserutils;1";
+
+const gMimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+var gIoService = null;
+
+const XMLNS = "http://www.w3.org/XML/1998/namespace";
+const RSS090NS = "http://my.netscape.com/rdf/simple/0.9/";
+
+/** *** Some general utils *****/
+function strToURI(link, base) {
+ base = base || null;
+ if (!gIoService)
+ gIoService = Cc[IO_CONTRACTID].getService(Ci.nsIIOService);
+ try {
+ return gIoService.newURI(link, null, base);
+ }
+ catch (e) {
+ return null;
+ }
+}
+
+function isArray(a) {
+ return isObject(a) && a.constructor == Array;
+}
+
+function isObject(a) {
+ return (a && typeof a == "object") || isFunction(a);
+}
+
+function isFunction(a) {
+ return typeof a == "function";
+}
+
+function isIID(a, iid) {
+ var rv = false;
+ try {
+ a.QueryInterface(iid);
+ rv = true;
+ }
+ catch (e) {
+ }
+ return rv;
+}
+
+function isIArray(a) {
+ return isIID(a, Ci.nsIArray);
+}
+
+function isIFeedContainer(a) {
+ return isIID(a, Ci.nsIFeedContainer);
+}
+
+function stripTags(someHTML) {
+ return someHTML.replace(/<[^>]+>/g, "");
+}
+
+/**
+ * Searches through an array of links and returns a JS array
+ * of matching property bags.
+ */
+const IANA_URI = "http://www.iana.org/assignments/relation/";
+function findAtomLinks(rel, links) {
+ var rvLinks = [];
+ for (var i = 0; i < links.length; ++i) {
+ var linkElement = links.queryElementAt(i, Ci.nsIPropertyBag2);
+ // atom:link MUST have @href
+ if (bagHasKey(linkElement, "href")) {
+ var relAttribute = null;
+ if (bagHasKey(linkElement, "rel"))
+ relAttribute = linkElement.getPropertyAsAString("rel")
+ if ((!relAttribute && rel == "alternate") || relAttribute == rel) {
+ rvLinks.push(linkElement);
+ continue;
+ }
+ // catch relations specified by IANA URI
+ if (relAttribute == IANA_URI + rel) {
+ rvLinks.push(linkElement);
+ }
+ }
+ }
+ return rvLinks;
+}
+
+function xmlEscape(s) {
+ s = s.replace(/&/g, "&amp;");
+ s = s.replace(/>/g, "&gt;");
+ s = s.replace(/</g, "&lt;");
+ s = s.replace(/"/g, "&quot;");
+ s = s.replace(/'/g, "&apos;");
+ return s;
+}
+
+function arrayContains(array, element) {
+ for (var i = 0; i < array.length; ++i) {
+ if (array[i] == element) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// XXX add hasKey to nsIPropertyBag
+function bagHasKey(bag, key) {
+ try {
+ bag.getProperty(key);
+ return true;
+ }
+ catch (e) {
+ return false;
+ }
+}
+
+function makePropGetter(key) {
+ return function FeedPropGetter(bag) {
+ try {
+ return value = bag.getProperty(key);
+ }
+ catch (e) {
+ }
+ return null;
+ }
+}
+
+const RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+// namespace map
+var gNamespaces = {
+ "http://webns.net/mvcb/":"admin",
+ "http://backend.userland.com/rss":"",
+ "http://blogs.law.harvard.edu/tech/rss":"",
+ "http://www.w3.org/2005/Atom":"atom",
+ "http://purl.org/atom/ns#":"atom03",
+ "http://purl.org/rss/1.0/modules/content/":"content",
+ "http://purl.org/dc/elements/1.1/":"dc",
+ "http://purl.org/dc/terms/":"dcterms",
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#":"rdf",
+ "http://purl.org/rss/1.0/":"rss1",
+ "http://my.netscape.com/rdf/simple/0.9/":"rss1",
+ "http://wellformedweb.org/CommentAPI/":"wfw",
+ "http://purl.org/rss/1.0/modules/wiki/":"wiki",
+ "http://www.w3.org/XML/1998/namespace":"xml",
+ "http://search.yahoo.com/mrss/":"media",
+ "http://search.yahoo.com/mrss":"media"
+}
+
+// We allow a very small set of namespaces in XHTML content,
+// for attributes only
+var gAllowedXHTMLNamespaces = {
+ "http://www.w3.org/XML/1998/namespace":"xml",
+ // if someone ns qualifies XHTML, we have to prefix it to avoid an
+ // attribute collision.
+ "http://www.w3.org/1999/xhtml":"xhtml"
+}
+
+function FeedResult() {}
+FeedResult.prototype = {
+ bozo: false,
+ doc: null,
+ version: null,
+ headers: null,
+ uri: null,
+ stylesheet: null,
+
+ registerExtensionPrefix: function FR_registerExtensionPrefix(ns, prefix) {
+ throw Cr.NS_ERROR_NOT_IMPLEMENTED;
+ },
+
+ // XPCOM stuff
+ classID: FR_CLASSID,
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIFeedResult])
+}
+
+function Feed() {
+ this.subtitle = null;
+ this.title = null;
+ this.items = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray);
+ this.link = null;
+ this.id = null;
+ this.generator = null;
+ this.authors = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray);
+ this.contributors = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray);
+ this.baseURI = null;
+ this.enclosureCount = 0;
+ this.type = Ci.nsIFeed.TYPE_FEED;
+}
+
+Feed.prototype = {
+ searchLists: {
+ title: ["title", "rss1:title", "atom03:title", "atom:title"],
+ subtitle: ["description", "dc:description", "rss1:description",
+ "atom03:tagline", "atom:subtitle"],
+ items: ["items", "atom03_entries", "entries"],
+ id: ["atom:id", "rdf:about"],
+ generator: ["generator"],
+ authors : ["authors"],
+ contributors: ["contributors"],
+ link: [["link", strToURI], ["rss1:link", strToURI]],
+ categories: ["categories", "dc:subject"],
+ rights: ["atom03:rights", "atom:rights"],
+ cloud: ["cloud"],
+ image: ["image", "rss1:image", "atom:logo"],
+ textInput: ["textInput", "rss1:textinput"],
+ skipDays: ["skipDays"],
+ skipHours: ["skipHours"],
+ updated: ["pubDate", "lastBuildDate", "atom03:modified", "dc:date",
+ "dcterms:modified", "atom:updated"]
+ },
+
+ normalize: function Feed_normalize() {
+ fieldsToObj(this, this.searchLists);
+ if (this.skipDays)
+ this.skipDays = this.skipDays.getProperty("days");
+ if (this.skipHours)
+ this.skipHours = this.skipHours.getProperty("hours");
+
+ if (this.updated)
+ this.updated = dateParse(this.updated);
+
+ // Assign Atom link if needed
+ if (bagHasKey(this.fields, "links"))
+ this._atomLinksToURI();
+
+ this._calcEnclosureCountAndFeedType();
+
+ // Resolve relative image links
+ if (this.image && bagHasKey(this.image, "url"))
+ this._resolveImageLink();
+
+ this._resetBagMembersToRawText([this.searchLists.subtitle,
+ this.searchLists.title]);
+ },
+
+ _calcEnclosureCountAndFeedType: function Feed_calcEnclosureCountAndFeedType() {
+ var entries_with_enclosures = 0;
+ var audio_count = 0;
+ var image_count = 0;
+ var video_count = 0;
+ var other_count = 0;
+
+ for (var i = 0; i < this.items.length; ++i) {
+ var entry = this.items.queryElementAt(i, Ci.nsIFeedEntry);
+ entry.QueryInterface(Ci.nsIFeedContainer);
+
+ if (entry.enclosures && entry.enclosures.length > 0) {
+ ++entries_with_enclosures;
+
+ for (var e = 0; e < entry.enclosures.length; ++e) {
+ var enc = entry.enclosures.queryElementAt(e, Ci.nsIWritablePropertyBag2);
+ if (enc.hasKey("type")) {
+ var enctype = enc.get("type");
+
+ if (/^audio/.test(enctype)) {
+ ++audio_count;
+ } else if (/^image/.test(enctype)) {
+ ++image_count;
+ } else if (/^video/.test(enctype)) {
+ ++video_count;
+ } else {
+ ++other_count;
+ }
+ } else {
+ ++other_count;
+ }
+ }
+ }
+ }
+
+ var feedtype = Ci.nsIFeed.TYPE_FEED;
+
+ // For a feed to be marked as TYPE_VIDEO, TYPE_AUDIO and TYPE_IMAGE,
+ // we enforce two things:
+ //
+ // 1. all entries must have at least one enclosure
+ // 2. all enclosures must be video for TYPE_VIDEO, audio for TYPE_AUDIO or image
+ // for TYPE_IMAGE
+ //
+ // Otherwise it's a TYPE_FEED.
+ if (entries_with_enclosures == this.items.length && other_count == 0) {
+ if (audio_count > 0 && !video_count && !image_count) {
+ feedtype = Ci.nsIFeed.TYPE_AUDIO;
+
+ } else if (image_count > 0 && !audio_count && !video_count) {
+ feedtype = Ci.nsIFeed.TYPE_IMAGE;
+
+ } else if (video_count > 0 && !audio_count && !image_count) {
+ feedtype = Ci.nsIFeed.TYPE_VIDEO;
+ }
+ }
+
+ this.type = feedtype;
+ this.enclosureCount = other_count + video_count + audio_count + image_count;
+ },
+
+ _atomLinksToURI: function Feed_linkToURI() {
+ var links = this.fields.getPropertyAsInterface("links", Ci.nsIArray);
+ var alternates = findAtomLinks("alternate", links);
+ if (alternates.length > 0) {
+ var href = alternates[0].getPropertyAsAString("href");
+ var base;
+ if (bagHasKey(alternates[0], "xml:base"))
+ base = alternates[0].getPropertyAsAString("xml:base");
+ this.link = this._resolveURI(href, base);
+ }
+ },
+
+ _resolveImageLink: function Feed_resolveImageLink() {
+ var base;
+ if (bagHasKey(this.image, "xml:base"))
+ base = this.image.getPropertyAsAString("xml:base");
+ var url = this._resolveURI(this.image.getPropertyAsAString("url"), base);
+ if (url)
+ this.image.setPropertyAsAString("url", url.spec);
+ },
+
+ _resolveURI: function Feed_resolveURI(linkSpec, baseSpec) {
+ var uri = null;
+ try {
+ var base = baseSpec ? strToURI(baseSpec, this.baseURI) : this.baseURI;
+ uri = strToURI(linkSpec, base);
+ }
+ catch (e) {
+ LOG(e);
+ }
+
+ return uri;
+ },
+
+ // reset the bag to raw contents, not text constructs
+ _resetBagMembersToRawText: function Feed_resetBagMembers(fieldLists) {
+ for (var i=0; i<fieldLists.length; i++) {
+ for (var j=0; j<fieldLists[i].length; j++) {
+ if (bagHasKey(this.fields, fieldLists[i][j])) {
+ var textConstruct = this.fields.getProperty(fieldLists[i][j]);
+ this.fields.setPropertyAsAString(fieldLists[i][j],
+ textConstruct.text);
+ }
+ }
+ }
+ },
+
+ // XPCOM stuff
+ classID: FEED_CLASSID,
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIFeed, Ci.nsIFeedContainer])
+}
+
+function Entry() {
+ this.summary = null;
+ this.content = null;
+ this.title = null;
+ this.fields = Cc["@mozilla.org/hash-property-bag;1"].
+ createInstance(Ci.nsIWritablePropertyBag2);
+ this.link = null;
+ this.id = null;
+ this.baseURI = null;
+ this.updated = null;
+ this.published = null;
+ this.authors = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray);
+ this.contributors = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray);
+}
+
+Entry.prototype = {
+ fields: null,
+ enclosures: null,
+ mediaContent: null,
+
+ searchLists: {
+ title: ["title", "rss1:title", "atom03:title", "atom:title"],
+ link: [["link", strToURI], ["rss1:link", strToURI]],
+ id: [["guid", makePropGetter("guid")], "rdf:about",
+ "atom03:id", "atom:id"],
+ authors : ["authors"],
+ contributors: ["contributors"],
+ summary: ["description", "rss1:description", "dc:description",
+ "atom03:summary", "atom:summary"],
+ content: ["content:encoded", "atom03:content", "atom:content"],
+ rights: ["atom03:rights", "atom:rights"],
+ published: ["pubDate", "atom03:issued", "dcterms:issued", "atom:published"],
+ updated: ["pubDate", "atom03:modified", "dc:date", "dcterms:modified",
+ "atom:updated"]
+ },
+
+ normalize: function Entry_normalize() {
+ fieldsToObj(this, this.searchLists);
+
+ // Assign Atom link if needed
+ if (bagHasKey(this.fields, "links"))
+ this._atomLinksToURI();
+
+ // Populate enclosures array
+ this._populateEnclosures();
+
+ // The link might be a guid w/ permalink=true
+ if (!this.link && bagHasKey(this.fields, "guid")) {
+ var guid = this.fields.getProperty("guid");
+ var isPermaLink = true;
+
+ if (bagHasKey(guid, "isPermaLink"))
+ isPermaLink = guid.getProperty("isPermaLink").toLowerCase() != "false";
+
+ if (guid && isPermaLink)
+ this.link = strToURI(guid.getProperty("guid"));
+ }
+
+ if (this.updated)
+ this.updated = dateParse(this.updated);
+ if (this.published)
+ this.published = dateParse(this.published);
+
+ this._resetBagMembersToRawText([this.searchLists.content,
+ this.searchLists.summary,
+ this.searchLists.title]);
+ },
+
+ _populateEnclosures: function Entry_populateEnclosures() {
+ if (bagHasKey(this.fields, "links"))
+ this._atomLinksToEnclosures();
+
+ // Add RSS2 enclosure to enclosures
+ if (bagHasKey(this.fields, "enclosure"))
+ this._enclosureToEnclosures();
+
+ // Add media:content to enclosures
+ if (bagHasKey(this.fields, "mediacontent"))
+ this._mediaToEnclosures("mediacontent");
+
+ // Add media:thumbnail to enclosures
+ if (bagHasKey(this.fields, "mediathumbnail"))
+ this._mediaToEnclosures("mediathumbnail");
+
+ // Add media:content in media:group to enclosures
+ if (bagHasKey(this.fields, "mediagroup"))
+ this._mediaToEnclosures("mediagroup", "mediacontent");
+ },
+
+ __enclosure_map: null,
+
+ _addToEnclosures: function Entry_addToEnclosures(new_enc) {
+ // items we add to the enclosures array get displayed in the FeedWriter and
+ // they must have non-empty urls.
+ if (!bagHasKey(new_enc, "url") || new_enc.getPropertyAsAString("url") == "")
+ return;
+
+ if (this.__enclosure_map == null)
+ this.__enclosure_map = {};
+
+ var previous_enc = this.__enclosure_map[new_enc.getPropertyAsAString("url")];
+
+ if (previous_enc != undefined) {
+ previous_enc.QueryInterface(Ci.nsIWritablePropertyBag2);
+
+ if (!bagHasKey(previous_enc, "type") && bagHasKey(new_enc, "type")) {
+ previous_enc.setPropertyAsAString("type", new_enc.getPropertyAsAString("type"));
+ try {
+ let handlerInfoWrapper = gMimeService.getFromTypeAndExtension(new_enc.getPropertyAsAString("type"), null);
+ if (handlerInfoWrapper && handlerInfoWrapper.description) {
+ previous_enc.setPropertyAsAString("typeDesc", handlerInfoWrapper.description);
+ }
+ } catch (ext) {}
+ }
+
+ if (!bagHasKey(previous_enc, "length") && bagHasKey(new_enc, "length"))
+ previous_enc.setPropertyAsAString("length", new_enc.getPropertyAsAString("length"));
+
+ return;
+ }
+
+ if (this.enclosures == null) {
+ this.enclosures = Cc[ARRAY_CONTRACTID].createInstance(Ci.nsIMutableArray);
+ this.enclosures.QueryInterface(Ci.nsIMutableArray);
+ }
+
+ this.enclosures.appendElement(new_enc, false);
+ this.__enclosure_map[new_enc.getPropertyAsAString("url")] = new_enc;
+ },
+
+ _atomLinksToEnclosures: function Entry_linkToEnclosure() {
+ var links = this.fields.getPropertyAsInterface("links", Ci.nsIArray);
+ var enc_links = findAtomLinks("enclosure", links);
+ if (enc_links.length == 0)
+ return;
+
+ for (var i = 0; i < enc_links.length; ++i) {
+ var link = enc_links[i];
+
+ // an enclosure must have an href
+ if (!(link.getProperty("href")))
+ return;
+
+ var enc = Cc[BAG_CONTRACTID].createInstance(Ci.nsIWritablePropertyBag2);
+
+ // copy Atom bits over to equivalent enclosure bits
+ enc.setPropertyAsAString("url", link.getPropertyAsAString("href"));
+ if (bagHasKey(link, "type"))
+ enc.setPropertyAsAString("type", link.getPropertyAsAString("type"));
+ if (bagHasKey(link, "length"))
+ enc.setPropertyAsAString("length", link.getPropertyAsAString("length"));
+
+ this._addToEnclosures(enc);
+ }
+ },
+
+ _enclosureToEnclosures: function Entry_enclosureToEnclosures() {
+ var enc = this.fields.getPropertyAsInterface("enclosure", Ci.nsIPropertyBag2);
+
+ if (!(enc.getProperty("url")))
+ return;
+
+ this._addToEnclosures(enc);
+ },
+
+ _mediaToEnclosures: function Entry_mediaToEnclosures(mediaType, contentType) {
+ var content;
+
+ // If a contentType is specified, the mediaType is a simple propertybag,
+ // and the contentType is an array inside it.
+ if (contentType) {
+ var group = this.fields.getPropertyAsInterface(mediaType, Ci.nsIPropertyBag2);
+ content = group.getPropertyAsInterface(contentType, Ci.nsIArray);
+ } else {
+ content = this.fields.getPropertyAsInterface(mediaType, Ci.nsIArray);
+ }
+
+ for (var i = 0; i < content.length; ++i) {
+ var contentElement = content.queryElementAt(i, Ci.nsIWritablePropertyBag2);
+
+ // media:content don't require url, but if it's not there, we should
+ // skip it.
+ if (!bagHasKey(contentElement, "url"))
+ continue;
+
+ var enc = Cc[BAG_CONTRACTID].createInstance(Ci.nsIWritablePropertyBag2);
+
+ // copy media:content bits over to equivalent enclosure bits
+ enc.setPropertyAsAString("url", contentElement.getPropertyAsAString("url"));
+ if (bagHasKey(contentElement, "type")) {
+ enc.setPropertyAsAString("type", contentElement.getPropertyAsAString("type"));
+ } else if (mediaType == "mediathumbnail") {
+ // thumbnails won't have a type, but default to image types
+ enc.setPropertyAsAString("type", "image/*");
+ enc.setPropertyAsBool("thumbnail", true);
+ }
+
+ if (bagHasKey(contentElement, "fileSize")) {
+ enc.setPropertyAsAString("length", contentElement.getPropertyAsAString("fileSize"));
+ }
+
+ this._addToEnclosures(enc);
+ }
+ },
+
+ // XPCOM stuff
+ classID: ENTRY_CLASSID,
+ QueryInterface: XPCOMUtils.generateQI(
+ [Ci.nsIFeedEntry, Ci.nsIFeedContainer]
+ )
+}
+
+Entry.prototype._atomLinksToURI = Feed.prototype._atomLinksToURI;
+Entry.prototype._resolveURI = Feed.prototype._resolveURI;
+Entry.prototype._resetBagMembersToRawText =
+ Feed.prototype._resetBagMembersToRawText;
+
+// TextConstruct represents and element that could contain (X)HTML
+function TextConstruct() {
+ this.lang = null;
+ this.base = null;
+ this.type = "text";
+ this.text = null;
+ this.parserUtils = Cc[PARSERUTILS_CONTRACTID].getService(Ci.nsIParserUtils);
+}
+
+TextConstruct.prototype = {
+ plainText: function TC_plainText() {
+ if (this.type != "text") {
+ return this.parserUtils.convertToPlainText(stripTags(this.text),
+ Ci.nsIDocumentEncoder.OutputSelectionOnly |
+ Ci.nsIDocumentEncoder.OutputAbsoluteLinks,
+ 0);
+ }
+ return this.text;
+ },
+
+ createDocumentFragment: function TC_createDocumentFragment(element) {
+ if (this.type == "text") {
+ var doc = element.ownerDocument;
+ var docFragment = doc.createDocumentFragment();
+ var node = doc.createTextNode(this.text);
+ docFragment.appendChild(node);
+ return docFragment;
+ }
+ var isXML;
+ if (this.type == "xhtml")
+ isXML = true
+ else if (this.type == "html")
+ isXML = false;
+ else
+ return null;
+
+ return this.parserUtils.parseFragment(this.text, 0, isXML,
+ this.base, element);
+ },
+
+ // XPCOM stuff
+ classID: TEXTCONSTRUCT_CLASSID,
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIFeedTextConstruct])
+}
+
+// Generator represents the software that produced the feed
+function Generator() {
+ this.lang = null;
+ this.agent = null;
+ this.version = null;
+ this.uri = null;
+
+ // nsIFeedElementBase
+ this._attributes = null;
+ this.baseURI = null;
+}
+
+Generator.prototype = {
+
+ get attributes() {
+ return this._attributes;
+ },
+
+ set attributes(value) {
+ this._attributes = value;
+ this.version = this._attributes.getValueFromName("", "version");
+ var uriAttribute = this._attributes.getValueFromName("", "uri") ||
+ this._attributes.getValueFromName("", "url");
+ this.uri = strToURI(uriAttribute, this.baseURI);
+
+ // RSS1
+ uriAttribute = this._attributes.getValueFromName(RDF_NS, "resource");
+ if (uriAttribute) {
+ this.agent = uriAttribute;
+ this.uri = strToURI(uriAttribute, this.baseURI);
+ }
+ },
+
+ // XPCOM stuff
+ classID: GENERATOR_CLASSID,
+ QueryInterface: XPCOMUtils.generateQI(
+ [Ci.nsIFeedGenerator, Ci.nsIFeedElementBase]
+ )
+}
+
+function Person() {
+ this.name = null;
+ this.uri = null;
+ this.email = null;
+
+ // nsIFeedElementBase
+ this.attributes = null;
+ this.baseURI = null;
+}
+
+Person.prototype = {
+ // XPCOM stuff
+ classID: PERSON_CLASSID,
+ QueryInterface: XPCOMUtils.generateQI(
+ [Ci.nsIFeedPerson, Ci.nsIFeedElementBase]
+ )
+}
+
+/**
+ * Map a list of fields into properties on a container.
+ *
+ * @param container An nsIFeedContainer
+ * @param fields A list of fields to search for. List members can
+ * be a list, in which case the second member is
+ * transformation function (like parseInt).
+ */
+function fieldsToObj(container, fields) {
+ var props, prop, field, searchList;
+ for (var key in fields) {
+ searchList = fields[key];
+ for (var i=0; i < searchList.length; ++i) {
+ props = searchList[i];
+ prop = null;
+ field = isArray(props) ? props[0] : props;
+ try {
+ prop = container.fields.getProperty(field);
+ }
+ catch (e) {
+ }
+ if (prop) {
+ prop = isArray(props) ? props[1](prop) : prop;
+ container[key] = prop;
+ }
+ }
+ }
+}
+
+/**
+ * Lower cases an element's localName property
+ * @param element A DOM element.
+ *
+ * @returns The lower case localName property of the specified element
+ */
+function LC(element) {
+ return element.localName.toLowerCase();
+}
+
+// TODO move these post-processor functions
+// create a generator element
+function atomGenerator(s, generator) {
+ generator.QueryInterface(Ci.nsIFeedGenerator);
+ generator.agent = s.trim();
+ return generator;
+}
+
+// post-process atom:logo to create an RSS2-like structure
+function atomLogo(s, logo) {
+ logo.setPropertyAsAString("url", s.trim());
+}
+
+// post-process an RSS category, map it to the Atom fields.
+function rssCatTerm(s, cat) {
+ // add slash handling?
+ cat.setPropertyAsAString("term", s.trim());
+ return cat;
+}
+
+// post-process a GUID
+function rssGuid(s, guid) {
+ guid.setPropertyAsAString("guid", s.trim());
+ return guid;
+}
+
+// post-process an RSS author element
+//
+// It can contain a field like this:
+//
+// <author>lawyer@boyer.net (Lawyer Boyer)</author>
+//
+// or, delightfully, a field like this:
+//
+// <dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>
+//
+// We want to split this up and assign it to corresponding Atom
+// fields.
+//
+function rssAuthor(s, author) {
+ author.QueryInterface(Ci.nsIFeedPerson);
+ // check for RSS2 string format
+ var chars = s.trim();
+ var matches = chars.match(/(.*)\((.*)\)/);
+ var emailCheck =
+ /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
+ if (matches) {
+ var match1 = matches[1].trim();
+ var match2 = matches[2].trim();
+ if (match2.indexOf("mailto:") == 0)
+ match2 = match2.substring(7);
+ if (emailCheck.test(match1)) {
+ author.email = match1;
+ author.name = match2;
+ }
+ else if (emailCheck.test(match2)) {
+ author.email = match2;
+ author.name = match1;
+ }
+ else {
+ // put it back together
+ author.name = match1 + " (" + match2 + ")";
+ }
+ }
+ else {
+ author.name = chars;
+ if (chars.indexOf('@'))
+ author.email = chars;
+ }
+ return author;
+}
+
+//
+// skipHours and skipDays map to arrays, so we need to change the
+// string to an nsISupports in order to stick it in there.
+//
+function rssArrayElement(s) {
+ var str = Cc["@mozilla.org/supports-string;1"].
+ createInstance(Ci.nsISupportsString);
+ str.data = s;
+ str.QueryInterface(Ci.nsISupportsString);
+ return str;
+}
+
+/**
+ * Tries parsing a string through the JavaScript Date object.
+ * @param aDateString
+ * A string that is supposedly an RFC822 or RFC3339 date.
+ * @return A Date.toUTCString, or null if the string can't be parsed.
+ */
+function dateParse(aDateString) {
+ let dateString = aDateString.trim();
+ // Without bug 682781 fixed, JS won't parse an RFC822 date with a Z for the
+ // timezone, so convert to -00:00 which works for any date format.
+ dateString = dateString.replace(/z$/i, "-00:00");
+ let date = new Date(dateString);
+ if (!isNaN(date)) {
+ return date.toUTCString();
+ }
+ return null;
+}
+
+const XHTML_NS = "http://www.w3.org/1999/xhtml";
+
+// The XHTMLHandler handles inline XHTML found in things like atom:summary
+function XHTMLHandler(processor, isAtom) {
+ this._buf = "";
+ this._processor = processor;
+ this._depth = 0;
+ this._isAtom = isAtom;
+ // a stack of lists tracking in-scope namespaces
+ this._inScopeNS = [];
+}
+
+// The fidelity can be improved here, to allow handling of stuff like
+// SVG and MathML. XXX
+XHTMLHandler.prototype = {
+
+ // look back up at the declared namespaces
+ // we always use the same prefixes for our safe stuff
+ _isInScope: function XH__isInScope(ns) {
+ for (var i in this._inScopeNS) {
+ for (var uri in this._inScopeNS[i]) {
+ if (this._inScopeNS[i][uri] == ns)
+ return true;
+ }
+ }
+ return false;
+ },
+
+ startDocument: function XH_startDocument() {
+ },
+ endDocument: function XH_endDocument() {
+ },
+ startElement: function XH_startElement(namespace, localName, qName, attributes) {
+ ++this._depth;
+ this._inScopeNS.push([]);
+
+ // RFC4287 requires XHTML to be wrapped in a div that is *not* part of
+ // the content. This prevents people from screwing up namespaces, but
+ // we need to skip it here.
+ if (this._isAtom && this._depth == 1 && localName == "div")
+ return;
+
+ // If it's an XHTML element, record it. Otherwise, it's ignored.
+ if (namespace == XHTML_NS) {
+ this._buf += "<" + localName;
+ var uri;
+ for (var i=0; i < attributes.length; ++i) {
+ uri = attributes.getURI(i);
+ // XHTML attributes aren't in a namespace
+ if (uri == "") {
+ this._buf += (" " + attributes.getLocalName(i) + "='" +
+ xmlEscape(attributes.getValue(i)) + "'");
+ } else {
+ // write a small set of allowed attribute namespaces
+ var prefix = gAllowedXHTMLNamespaces[uri];
+ if (prefix != null) {
+ // The attribute value we'll attempt to write
+ var attributeValue = xmlEscape(attributes.getValue(i));
+
+ // it's an allowed attribute NS.
+ // write the attribute
+ this._buf += (" " + prefix + ":" +
+ attributes.getLocalName(i) +
+ "='" + attributeValue + "'");
+
+ // write an xmlns declaration if necessary
+ if (prefix != "xml" && !this._isInScope(uri)) {
+ this._inScopeNS[this._inScopeNS.length - 1].push(uri);
+ this._buf += " xmlns:" + prefix + "='" + uri + "'";
+ }
+ }
+ }
+ }
+ this._buf += ">";
+ }
+ },
+ endElement: function XH_endElement(uri, localName, qName) {
+ --this._depth;
+ this._inScopeNS.pop();
+
+ // We need to skip outer divs in Atom. See comment in startElement.
+ if (this._isAtom && this._depth == 0 && localName == "div")
+ return;
+
+ // When we peek too far, go back to the main processor
+ if (this._depth < 0) {
+ this._processor.returnFromXHTMLHandler(this._buf.trim(),
+ uri, localName, qName);
+ return;
+ }
+ // If it's an XHTML element, record it. Otherwise, it's ignored.
+ if (uri == XHTML_NS) {
+ this._buf += "</" + localName + ">";
+ }
+ },
+ characters: function XH_characters(data) {
+ this._buf += xmlEscape(data);
+ },
+ startPrefixMapping: function XH_startPrefixMapping(prefix, uri) {
+ },
+ endPrefixMapping: function FP_endPrefixMapping(prefix) {
+ },
+ processingInstruction: function XH_processingInstruction() {
+ },
+}
+
+/**
+ * The ExtensionHandler deals with elements we haven't explicitly
+ * added to our transition table in the FeedProcessor.
+ */
+function ExtensionHandler(processor) {
+ this._buf = "";
+ this._depth = 0;
+ this._hasChildElements = false;
+
+ // The FeedProcessor
+ this._processor = processor;
+
+ // Fields of the outermost extension element.
+ this._localName = null;
+ this._uri = null;
+ this._qName = null;
+ this._attrs = null;
+}
+
+ExtensionHandler.prototype = {
+ startDocument: function EH_startDocument() {
+ },
+ endDocument: function EH_endDocument() {
+ },
+ startElement: function EH_startElement(uri, localName, qName, attrs) {
+ ++this._depth;
+
+ if (this._depth == 1) {
+ this._uri = uri;
+ this._localName = localName;
+ this._qName = qName;
+ this._attrs = attrs;
+ }
+
+ // if we descend into another element, we won't send text
+ this._hasChildElements = (this._depth > 1);
+
+ },
+ endElement: function EH_endElement(uri, localName, qName) {
+ --this._depth;
+ if (this._depth == 0) {
+ var text = this._hasChildElements ? null : this._buf.trim();
+ this._processor.returnFromExtHandler(this._uri, this._localName,
+ text, this._attrs);
+ }
+ },
+ characters: function EH_characters(data) {
+ if (!this._hasChildElements)
+ this._buf += data;
+ },
+ startPrefixMapping: function EH_startPrefixMapping() {
+ },
+ endPrefixMapping: function EH_endPrefixMapping() {
+ },
+ processingInstruction: function EH_processingInstruction() {
+ },
+};
+
+
+/**
+ * ElementInfo is a simple container object that describes
+ * some characteristics of a feed element. For example, it
+ * says whether an element can be expected to appear more
+ * than once inside a given entry or feed.
+ */
+function ElementInfo(fieldName, containerClass, closeFunc, isArray) {
+ this.fieldName = fieldName;
+ this.containerClass = containerClass;
+ this.closeFunc = closeFunc;
+ this.isArray = isArray;
+ this.isWrapper = false;
+}
+
+/**
+ * FeedElementInfo represents a feed element, usually the root.
+ */
+function FeedElementInfo(fieldName, feedVersion) {
+ this.isWrapper = false;
+ this.fieldName = fieldName;
+ this.feedVersion = feedVersion;
+}
+
+/**
+ * Some feed formats include vestigial wrapper elements that we don't
+ * want to include in our object model, but we do need to keep track
+ * of during parsing.
+ */
+function WrapperElementInfo(fieldName) {
+ this.isWrapper = true;
+ this.fieldName = fieldName;
+}
+
+/** *** The Processor *****/
+function FeedProcessor() {
+ this._reader = Cc[SAX_CONTRACTID].createInstance(Ci.nsISAXXMLReader);
+ this._buf = "";
+ this._feed = Cc[BAG_CONTRACTID].createInstance(Ci.nsIWritablePropertyBag2);
+ this._handlerStack = [];
+ this._xmlBaseStack = []; // sparse array keyed to nesting depth
+ this._depth = 0;
+ this._state = "START";
+ this._result = null;
+ this._extensionHandler = null;
+ this._xhtmlHandler = null;
+ this._haveSentResult = false;
+
+ // The nsIFeedResultListener waiting for the parse results
+ this.listener = null;
+
+ // These elements can contain (X)HTML or plain text.
+ // We keep a table here that contains their default treatment
+ this._textConstructs = {"atom:title":"text",
+ "atom:summary":"text",
+ "atom:rights":"text",
+ "atom:content":"text",
+ "atom:subtitle":"text",
+ "description":"html",
+ "rss1:description":"html",
+ "dc:description":"html",
+ "content:encoded":"html",
+ "title":"text",
+ "rss1:title":"text",
+ "atom03:title":"text",
+ "atom03:tagline":"text",
+ "atom03:summary":"text",
+ "atom03:content":"text"};
+ this._stack = [];
+
+ this._trans = {
+ "START": {
+ // If we hit a root RSS element, treat as RSS2.
+ "rss": new FeedElementInfo("RSS2", "rss2"),
+
+ // If we hit an RDF element, if could be RSS1, but we can't
+ // verify that until we hit a rss1:channel element.
+ "rdf:RDF": new WrapperElementInfo("RDF"),
+
+ // If we hit a Atom 1.0 element, treat as Atom 1.0.
+ "atom:feed": new FeedElementInfo("Atom", "atom"),
+
+ // Treat as Atom 0.3
+ "atom03:feed": new FeedElementInfo("Atom03", "atom03"),
+ },
+
+ /** ******* RSS2 **********/
+ "IN_RSS2": {
+ "channel": new WrapperElementInfo("channel")
+ },
+
+ "IN_CHANNEL": {
+ "item": new ElementInfo("items", Cc[ENTRY_CONTRACTID], null, true),
+ "managingEditor": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
+ rssAuthor, true),
+ "dc:creator": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
+ rssAuthor, true),
+ "dc:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
+ rssAuthor, true),
+ "dc:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID],
+ rssAuthor, true),
+ "category": new ElementInfo("categories", null, rssCatTerm, true),
+ "cloud": new ElementInfo("cloud", null, null, false),
+ "image": new ElementInfo("image", null, null, false),
+ "textInput": new ElementInfo("textInput", null, null, false),
+ "skipDays": new ElementInfo("skipDays", null, null, false),
+ "skipHours": new ElementInfo("skipHours", null, null, false),
+ "generator": new ElementInfo("generator", Cc[GENERATOR_CONTRACTID],
+ atomGenerator, false),
+ },
+
+ "IN_ITEMS": {
+ "author": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
+ rssAuthor, true),
+ "dc:creator": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
+ rssAuthor, true),
+ "dc:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
+ rssAuthor, true),
+ "dc:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID],
+ rssAuthor, true),
+ "category": new ElementInfo("categories", null, rssCatTerm, true),
+ "enclosure": new ElementInfo("enclosure", null, null, false),
+ "media:content": new ElementInfo("mediacontent", null, null, true),
+ "media:group": new ElementInfo("mediagroup", null, null, false),
+ "media:thumbnail": new ElementInfo("mediathumbnail", null, null, true),
+ "guid": new ElementInfo("guid", null, rssGuid, false)
+ },
+
+ "IN_SKIPDAYS": {
+ "day": new ElementInfo("days", null, rssArrayElement, true)
+ },
+
+ "IN_SKIPHOURS":{
+ "hour": new ElementInfo("hours", null, rssArrayElement, true)
+ },
+
+ "IN_MEDIAGROUP": {
+ "media:content": new ElementInfo("mediacontent", null, null, true),
+ "media:thumbnail": new ElementInfo("mediathumbnail", null, null, true)
+ },
+
+ /** ******* RSS1 **********/
+ "IN_RDF": {
+ // If we hit a rss1:channel, we can verify that we have RSS1
+ "rss1:channel": new FeedElementInfo("rdf_channel", "rss1"),
+ "rss1:image": new ElementInfo("image", null, null, false),
+ "rss1:textinput": new ElementInfo("textInput", null, null, false),
+ "rss1:item": new ElementInfo("items", Cc[ENTRY_CONTRACTID], null, true),
+ },
+
+ "IN_RDF_CHANNEL": {
+ "admin:generatorAgent": new ElementInfo("generator",
+ Cc[GENERATOR_CONTRACTID],
+ null, false),
+ "dc:creator": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
+ rssAuthor, true),
+ "dc:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
+ rssAuthor, true),
+ "dc:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID],
+ rssAuthor, true),
+ },
+
+ /** ******* ATOM 1.0 **********/
+ "IN_ATOM": {
+ "atom:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
+ null, true),
+ "atom:generator": new ElementInfo("generator", Cc[GENERATOR_CONTRACTID],
+ atomGenerator, false),
+ "atom:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID],
+ null, true),
+ "atom:link": new ElementInfo("links", null, null, true),
+ "atom:logo": new ElementInfo("atom:logo", null, atomLogo, false),
+ "atom:entry": new ElementInfo("entries", Cc[ENTRY_CONTRACTID],
+ null, true)
+ },
+
+ "IN_ENTRIES": {
+ "atom:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
+ null, true),
+ "atom:contributor": new ElementInfo("contributors", Cc[PERSON_CONTRACTID],
+ null, true),
+ "atom:link": new ElementInfo("links", null, null, true),
+ },
+
+ /** ******* ATOM 0.3 **********/
+ "IN_ATOM03": {
+ "atom03:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
+ null, true),
+ "atom03:contributor": new ElementInfo("contributors",
+ Cc[PERSON_CONTRACTID],
+ null, true),
+ "atom03:link": new ElementInfo("links", null, null, true),
+ "atom03:entry": new ElementInfo("atom03_entries", Cc[ENTRY_CONTRACTID],
+ null, true),
+ "atom03:generator": new ElementInfo("generator", Cc[GENERATOR_CONTRACTID],
+ atomGenerator, false),
+ },
+
+ "IN_ATOM03_ENTRIES": {
+ "atom03:author": new ElementInfo("authors", Cc[PERSON_CONTRACTID],
+ null, true),
+ "atom03:contributor": new ElementInfo("contributors",
+ Cc[PERSON_CONTRACTID],
+ null, true),
+ "atom03:link": new ElementInfo("links", null, null, true),
+ "atom03:entry": new ElementInfo("atom03_entries", Cc[ENTRY_CONTRACTID],
+ null, true)
+ }
+ }
+}
+
+// See startElement for a long description of how feeds are processed.
+FeedProcessor.prototype = {
+
+ // Set ourselves as the SAX handler, and set the base URI
+ _init: function FP_init(uri) {
+ this._reader.contentHandler = this;
+ this._reader.errorHandler = this;
+ this._result = Cc[FR_CONTRACTID].createInstance(Ci.nsIFeedResult);
+ if (uri) {
+ this._result.uri = uri;
+ this._reader.baseURI = uri;
+ this._xmlBaseStack[0] = uri;
+ }
+ },
+
+ // This function is called once we figure out what type of feed
+ // we're dealing with. Some feed types require digging a bit further
+ // than the root.
+ _docVerified: function FP_docVerified(version) {
+ this._result.doc = Cc[FEED_CONTRACTID].createInstance(Ci.nsIFeed);
+ this._result.doc.baseURI =
+ this._xmlBaseStack[this._xmlBaseStack.length - 1];
+ this._result.doc.fields = this._feed;
+ this._result.version = version;
+ },
+
+ // When we're done with the feed, let the listener know what
+ // happened.
+ _sendResult: function FP_sendResult() {
+ this._haveSentResult = true;
+ try {
+ // Can be null when a non-feed is fed to us
+ if (this._result.doc)
+ this._result.doc.normalize();
+ }
+ catch (e) {
+ LOG("FIXME: " + e);
+ }
+
+ try {
+ if (this.listener != null)
+ this.listener.handleResult(this._result);
+ }
+ finally {
+ this._result = null;
+ }
+ },
+
+ // Parsing functions
+ parseFromStream: function FP_parseFromStream(stream, uri) {
+ this._init(uri);
+ this._reader.parseFromStream(stream, null, stream.available(),
+ "application/xml");
+ this._reader = null;
+ },
+
+ parseFromString: function FP_parseFromString(inputString, uri) {
+ this._init(uri);
+ this._reader.parseFromString(inputString, "application/xml");
+ this._reader = null;
+ },
+
+ parseAsync: function FP_parseAsync(requestObserver, uri) {
+ this._init(uri);
+ this._reader.parseAsync(requestObserver);
+ },
+
+ // nsIStreamListener
+
+ // The XMLReader will throw sensible exceptions if these get called
+ // out of order.
+ onStartRequest: function FP_onStartRequest(request, context) {
+ // this will throw if the request is not a channel, but so will nsParser.
+ var channel = request.QueryInterface(Ci.nsIChannel);
+ channel.contentType = "application/vnd.mozilla.maybe.feed";
+ this._reader.onStartRequest(request, context);
+ },
+
+ onStopRequest: function FP_onStopRequest(request, context, statusCode) {
+ try {
+ this._reader.onStopRequest(request, context, statusCode);
+ }
+ finally {
+ this._reader = null;
+ }
+ },
+
+ onDataAvailable:
+ function FP_onDataAvailable(request, context, inputStream, offset, count) {
+ this._reader.onDataAvailable(request, context, inputStream, offset, count);
+ },
+
+ // nsISAXErrorHandler
+
+ // We only care about fatal errors. When this happens, we may have
+ // parsed through the feed metadata and some number of entries. The
+ // listener can still show some of that data if it wants, and we'll
+ // set the bozo bit to indicate we were unable to parse all the way
+ // through.
+ fatalError: function FP_reportError() {
+ this._result.bozo = true;
+ // XXX need to QI to FeedProgressListener
+ if (!this._haveSentResult)
+ this._sendResult();
+ },
+
+ // nsISAXContentHandler
+
+ startDocument: function FP_startDocument() {
+ // LOG("----------");
+ },
+
+ endDocument: function FP_endDocument() {
+ if (!this._haveSentResult)
+ this._sendResult();
+ },
+
+ // The transitions defined above identify elements that contain more
+ // than just text. For example RSS items contain many fields, and so
+ // do Atom authors. The only commonly used elements that contain
+ // mixed content are Atom Text Constructs of type="xhtml", which we
+ // delegate to another handler for cleaning. That leaves a couple
+ // different types of elements to deal with: those that should occur
+ // only once, such as title elements, and those that can occur
+ // multiple times, such as the RSS category element and the Atom
+ // link element. Most of the RSS1/DC elements can occur multiple
+ // times in theory, but in practice, the only ones that do have
+ // analogues in Atom.
+ //
+ // Some elements are also groups of attributes or sub-elements,
+ // while others are simple text fields. For the most part, we don't
+ // have to pay explicit attention to the simple text elements,
+ // unless we want to post-process the resulting string to transform
+ // it into some richer object like a Date or URI.
+ //
+ // Elements that have more sophisticated content models still end up
+ // being dictionaries, whether they are based on attributes like RSS
+ // cloud, sub-elements like Atom author, or even items and
+ // entries. These elements are treated as "containers". It's
+ // theoretically possible for a container to have an attribute with
+ // the same universal name as a sub-element, but none of the feed
+ // formats allow this by default, and I don't of any extension that
+ // works this way.
+ //
+ startElement: function FP_startElement(uri, localName, qName, attributes) {
+ this._buf = "";
+ ++this._depth;
+ var elementInfo;
+
+ // LOG("<" + localName + ">");
+
+ // Check for xml:base
+ var base = attributes.getValueFromName(XMLNS, "base");
+ if (base) {
+ this._xmlBaseStack[this._depth] =
+ strToURI(base, this._xmlBaseStack[this._xmlBaseStack.length - 1]);
+ }
+
+ // To identify the element we're dealing with, we look up the
+ // namespace URI in our gNamespaces dictionary, which will give us
+ // a "canonical" prefix for a namespace URI. For example, this
+ // allows Dublin Core "creator" elements to be consistently mapped
+ // to "dc:creator", for easy field access by consumer code. This
+ // strategy also happens to shorten up our state table.
+ var key = this._prefixForNS(uri) + localName;
+
+ // Check to see if we need to hand this off to our XHTML handler.
+ // The elements we're dealing with will look like this:
+ //
+ // <title type="xhtml">
+ // <div xmlns="http://www.w3.org/1999/xhtml">
+ // A title with <b>bold</b> and <i>italics</i>.
+ // </div>
+ // </title>
+ //
+ // When it returns in returnFromXHTMLHandler, the handler should
+ // give us back a string like this:
+ //
+ // "A title with <b>bold</b> and <i>italics</i>."
+ //
+ // The Atom spec explicitly says the div is not part of the content,
+ // and explicitly allows whitespace collapsing.
+ //
+ if ((this._result.version == "atom" || this._result.version == "atom03") &&
+ this._textConstructs[key] != null) {
+ var type = attributes.getValueFromName("", "type");
+ if (type != null && type.indexOf("xhtml") >= 0) {
+ this._xhtmlHandler =
+ new XHTMLHandler(this, (this._result.version == "atom"));
+ this._reader.contentHandler = this._xhtmlHandler;
+ return;
+ }
+ }
+
+ // Check our current state, and see if that state has a defined
+ // transition. For example, this._trans["atom:entry"]["atom:author"]
+ // will have one, and it tells us to add an item to our authors array.
+ if (this._trans[this._state] && this._trans[this._state][key]) {
+ elementInfo = this._trans[this._state][key];
+ }
+ else {
+ // If we don't have a transition, hand off to extension handler
+ this._extensionHandler = new ExtensionHandler(this);
+ this._reader.contentHandler = this._extensionHandler;
+ this._extensionHandler.startElement(uri, localName, qName, attributes);
+ return;
+ }
+
+ // This distinguishes wrappers like 'channel' from elements
+ // we'd actually like to do something with (which will test true).
+ this._handlerStack[this._depth] = elementInfo;
+ if (elementInfo.isWrapper) {
+ this._state = "IN_" + elementInfo.fieldName.toUpperCase();
+ this._stack.push([this._feed, this._state]);
+ }
+ else if (elementInfo.feedVersion) {
+ this._state = "IN_" + elementInfo.fieldName.toUpperCase();
+
+ // Check for the older RSS2 variants
+ if (elementInfo.feedVersion == "rss2")
+ elementInfo.feedVersion = this._findRSSVersion(attributes);
+ else if (uri == RSS090NS)
+ elementInfo.feedVersion = "rss090";
+
+ this._docVerified(elementInfo.feedVersion);
+ this._stack.push([this._feed, this._state]);
+ this._mapAttributes(this._feed, attributes);
+ }
+ else {
+ this._state = this._processComplexElement(elementInfo, attributes);
+ }
+ },
+
+ // In the endElement handler, we decrement the stack and look
+ // for cleanup/transition functions to execute. The second part
+ // of the state transition works as above in startElement, but
+ // the state we're looking for is prefixed with an underscore
+ // to distinguish endElement events from startElement events.
+ endElement: function FP_endElement(uri, localName, qName) {
+ var elementInfo = this._handlerStack[this._depth];
+ // LOG("</" + localName + ">");
+ if (elementInfo && !elementInfo.isWrapper)
+ this._closeComplexElement(elementInfo);
+
+ // cut down xml:base context
+ if (this._xmlBaseStack.length == this._depth + 1)
+ this._xmlBaseStack = this._xmlBaseStack.slice(0, this._depth);
+
+ // our new state is whatever is at the top of the stack now
+ if (this._stack.length > 0)
+ this._state = this._stack[this._stack.length - 1][1];
+ this._handlerStack = this._handlerStack.slice(0, this._depth);
+ --this._depth;
+ },
+
+ // Buffer up character data. The buffer is cleared with every
+ // opening element.
+ characters: function FP_characters(data) {
+ this._buf += data;
+ },
+ // TODO: It would be nice to check new prefixes here, and if they
+ // don't conflict with the ones we've defined, throw them in a
+ // dictionary to check.
+ startPrefixMapping: function FP_startPrefixMapping(prefix, uri) {
+ },
+
+ endPrefixMapping: function FP_endPrefixMapping(prefix) {
+ },
+
+ processingInstruction: function FP_processingInstruction(target, data) {
+ if (target == "xml-stylesheet") {
+ var hrefAttribute = data.match(/href=[\"\'](.*?)[\"\']/);
+ if (hrefAttribute && hrefAttribute.length == 2)
+ this._result.stylesheet = strToURI(hrefAttribute[1], this._result.uri);
+ }
+ },
+
+ // end of nsISAXContentHandler
+
+ // Handle our more complicated elements--those that contain
+ // attributes and child elements.
+ _processComplexElement:
+ function FP__processComplexElement(elementInfo, attributes) {
+ var obj;
+
+ // If the container is an entry/item, it'll need to have its
+ // more esoteric properties put in the 'fields' property bag.
+ if (elementInfo.containerClass == Cc[ENTRY_CONTRACTID]) {
+ obj = elementInfo.containerClass.createInstance(Ci.nsIFeedEntry);
+ obj.baseURI = this._xmlBaseStack[this._xmlBaseStack.length - 1];
+ this._mapAttributes(obj.fields, attributes);
+ }
+ else if (elementInfo.containerClass) {
+ obj = elementInfo.containerClass.createInstance(Ci.nsIFeedElementBase);
+ obj.baseURI = this._xmlBaseStack[this._xmlBaseStack.length - 1];
+ obj.attributes = attributes; // just set the SAX attributes
+ }
+ else {
+ obj = Cc[BAG_CONTRACTID].createInstance(Ci.nsIWritablePropertyBag2);
+ this._mapAttributes(obj, attributes);
+ }
+
+ // We should have a container/propertyBag that's had its
+ // attributes processed. Now we need to attach it to its
+ // container.
+ var newProp;
+
+ // First we'll see what's on top of the stack.
+ var container = this._stack[this._stack.length - 1][0];
+
+ // Check to see if it has the property
+ var prop;
+ try {
+ prop = container.getProperty(elementInfo.fieldName);
+ }
+ catch (e) {
+ }
+
+ if (elementInfo.isArray) {
+ if (!prop) {
+ container.setPropertyAsInterface(elementInfo.fieldName,
+ Cc[ARRAY_CONTRACTID].
+ createInstance(Ci.nsIMutableArray));
+ }
+
+ newProp = container.getProperty(elementInfo.fieldName);
+ // XXX This QI should not be necessary, but XPConnect seems to fly
+ // off the handle in the browser, and loses track of the interface
+ // on large files. Bug 335638.
+ newProp.QueryInterface(Ci.nsIMutableArray);
+ newProp.appendElement(obj, false);
+
+ // If new object is an nsIFeedContainer, we want to deal with
+ // its member nsIPropertyBag instead.
+ if (isIFeedContainer(obj))
+ newProp = obj.fields;
+
+ }
+ else {
+ // If it doesn't, set it.
+ if (!prop) {
+ container.setPropertyAsInterface(elementInfo.fieldName, obj);
+ }
+ newProp = container.getProperty(elementInfo.fieldName);
+ }
+
+ // make our new state name, and push the property onto the stack
+ var newState = "IN_" + elementInfo.fieldName.toUpperCase();
+ this._stack.push([newProp, newState, obj]);
+ return newState;
+ },
+
+ // Sometimes we need reconcile the element content with the object
+ // model for a given feed. We use helper functions to do the
+ // munging, but we need to identify array types here, so the munging
+ // happens only to the last element of an array.
+ _closeComplexElement: function FP__closeComplexElement(elementInfo) {
+ var stateTuple = this._stack.pop();
+ var container = stateTuple[0];
+ var containerParent = stateTuple[2];
+ var element = null;
+ var isArray = isIArray(container);
+
+ // If it's an array and we have to post-process,
+ // grab the last element
+ if (isArray)
+ element = container.queryElementAt(container.length - 1, Ci.nsISupports);
+ else
+ element = container;
+
+ // Run the post-processing function if there is one.
+ if (elementInfo.closeFunc)
+ element = elementInfo.closeFunc(this._buf, element);
+
+ // If an nsIFeedContainer was on top of the stack,
+ // we need to normalize it
+ if (elementInfo.containerClass == Cc[ENTRY_CONTRACTID])
+ containerParent.normalize();
+
+ // If it's an array, re-set the last element
+ if (isArray)
+ container.replaceElementAt(element, container.length - 1, false);
+ },
+
+ _prefixForNS: function FP_prefixForNS(uri) {
+ if (!uri)
+ return "";
+ var prefix = gNamespaces[uri];
+ if (prefix)
+ return prefix + ":";
+ if (uri.toLowerCase().indexOf("http://backend.userland.com") == 0)
+ return "";
+ return null;
+ },
+
+ _mapAttributes: function FP__mapAttributes(bag, attributes) {
+ // Cycle through the attributes, and set our properties using the
+ // prefix:localNames we find in our namespace dictionary.
+ for (var i = 0; i < attributes.length; ++i) {
+ var key = this._prefixForNS(attributes.getURI(i)) + attributes.getLocalName(i);
+ var val = attributes.getValue(i);
+ bag.setPropertyAsAString(key, val);
+ }
+ },
+
+ // Only for RSS2esque formats
+ _findRSSVersion: function FP__findRSSVersion(attributes) {
+ var versionAttr = attributes.getValueFromName("", "version").trim();
+ var versions = { "0.91":"rss091",
+ "0.92":"rss092",
+ "0.93":"rss093",
+ "0.94":"rss094" }
+ if (versions[versionAttr])
+ return versions[versionAttr];
+ if (versionAttr.substr(0, 2) != "2.")
+ return "rssUnknown";
+ return "rss2";
+ },
+
+ // unknown element values are returned here. See startElement above
+ // for how this works.
+ returnFromExtHandler:
+ function FP_returnExt(uri, localName, chars, attributes) {
+ --this._depth;
+
+ // take control of the SAX events
+ this._reader.contentHandler = this;
+ if (localName == null && chars == null)
+ return;
+
+ // we don't take random elements inside rdf:RDF
+ if (this._state == "IN_RDF")
+ return;
+
+ // Grab the top of the stack
+ var top = this._stack[this._stack.length - 1];
+ if (!top)
+ return;
+
+ var container = top[0];
+ // Grab the last element if it's an array
+ if (isIArray(container)) {
+ var contract = this._handlerStack[this._depth].containerClass;
+ // check if it's something specific, but not an entry
+ if (contract && contract != Cc[ENTRY_CONTRACTID]) {
+ var el = container.queryElementAt(container.length - 1,
+ Ci.nsIFeedElementBase);
+ // XXX there must be a way to flatten these interfaces
+ if (contract == Cc[PERSON_CONTRACTID])
+ el.QueryInterface(Ci.nsIFeedPerson);
+ else
+ return; // don't know about this interface
+
+ let propName = localName;
+ var prefix = gNamespaces[uri];
+
+ // synonyms
+ if ((uri == "" ||
+ prefix &&
+ ((prefix.indexOf("atom") > -1) ||
+ (prefix.indexOf("rss") > -1))) &&
+ (propName == "url" || propName == "href"))
+ propName = "uri";
+
+ try {
+ if (el[propName] !== "undefined") {
+ var propValue = chars;
+ // convert URI-bearing values to an nsIURI
+ if (propName == "uri") {
+ var base = this._xmlBaseStack[this._xmlBaseStack.length - 1];
+ propValue = strToURI(chars, base);
+ }
+ el[propName] = propValue;
+ }
+ }
+ catch (e) {
+ // ignore XPConnect errors
+ }
+ // the rest of the function deals with entry- and feed-level stuff
+ return;
+ }
+ container = container.queryElementAt(container.length - 1,
+ Ci.nsIWritablePropertyBag2);
+ }
+
+ // Make the buffer our new property
+ var propName = this._prefixForNS(uri) + localName;
+
+ // But, it could be something containing HTML. If so,
+ // we need to know about that.
+ if (this._textConstructs[propName] != null &&
+ this._handlerStack[this._depth].containerClass !== null) {
+ var newProp = Cc[TEXTCONSTRUCT_CONTRACTID].
+ createInstance(Ci.nsIFeedTextConstruct);
+ newProp.text = chars;
+ // Look up the default type in our table
+ var type = this._textConstructs[propName];
+ var typeAttribute = attributes.getValueFromName("", "type");
+ if (this._result.version == "atom" && typeAttribute != null) {
+ type = typeAttribute;
+ }
+ else if (this._result.version == "atom03" && typeAttribute != null) {
+ if (typeAttribute.toLowerCase().indexOf("xhtml") >= 0) {
+ type = "xhtml";
+ }
+ else if (typeAttribute.toLowerCase().indexOf("html") >= 0) {
+ type = "html";
+ }
+ else if (typeAttribute.toLowerCase().indexOf("text") >= 0) {
+ type = "text";
+ }
+ }
+
+ // If it's rss feed-level description, it's not supposed to have html
+ if (this._result.version.indexOf("rss") >= 0 &&
+ this._handlerStack[this._depth].containerClass != ENTRY_CONTRACTID) {
+ type = "text";
+ }
+ newProp.type = type;
+ newProp.base = this._xmlBaseStack[this._xmlBaseStack.length - 1];
+ container.setPropertyAsInterface(propName, newProp);
+ }
+ else {
+ container.setPropertyAsAString(propName, chars);
+ }
+ },
+
+ // Sometimes, we'll hand off SAX handling duties to an XHTMLHandler
+ // (see above) that will scrape out non-XHTML stuff, normalize
+ // namespaces, and remove the wrapper div from Atom 1.0. When the
+ // XHTMLHandler is done, it'll callback here.
+ returnFromXHTMLHandler:
+ function FP_returnFromXHTMLHandler(chars, uri, localName, qName) {
+ // retake control of the SAX content events
+ this._reader.contentHandler = this;
+
+ // Grab the top of the stack
+ var top = this._stack[this._stack.length - 1];
+ if (!top)
+ return;
+ var container = top[0];
+
+ // Assign the property
+ var newProp = newProp = Cc[TEXTCONSTRUCT_CONTRACTID].
+ createInstance(Ci.nsIFeedTextConstruct);
+ newProp.text = chars;
+ newProp.type = "xhtml";
+ newProp.base = this._xmlBaseStack[this._xmlBaseStack.length - 1];
+ container.setPropertyAsInterface(this._prefixForNS(uri) + localName,
+ newProp);
+
+ // XHTML will cause us to peek too far. The XHTML handler will
+ // send us an end element to call. RFC4287-valid feeds allow a
+ // more graceful way to handle this. Unfortunately, we can't count
+ // on compliance at this point.
+ this.endElement(uri, localName, qName);
+ },
+
+ // XPCOM stuff
+ classID: FP_CLASSID,
+ QueryInterface: XPCOMUtils.generateQI(
+ [Ci.nsIFeedProcessor, Ci.nsISAXContentHandler, Ci.nsISAXErrorHandler,
+ Ci.nsIStreamListener, Ci.nsIRequestObserver]
+ )
+}
+
+var components = [FeedProcessor, FeedResult, Feed, Entry,
+ TextConstruct, Generator, Person];
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
diff --git a/toolkit/components/feeds/FeedProcessor.manifest b/toolkit/components/feeds/FeedProcessor.manifest
new file mode 100644
index 000000000..5081d70c5
--- /dev/null
+++ b/toolkit/components/feeds/FeedProcessor.manifest
@@ -0,0 +1,14 @@
+component {072a5c3d-30c6-4f07-b87f-9f63d51403f2} FeedProcessor.js
+contract @mozilla.org/feed-result;1 {072a5c3d-30c6-4f07-b87f-9f63d51403f2}
+component {5d0cfa97-69dd-4e5e-ac84-f253162e8f9a} FeedProcessor.js
+contract @mozilla.org/feed;1 {5d0cfa97-69dd-4e5e-ac84-f253162e8f9a}
+component {8e4444ff-8e99-4bdd-aa7f-fb3c1c77319f} FeedProcessor.js
+contract @mozilla.org/feed-entry;1 {8e4444ff-8e99-4bdd-aa7f-fb3c1c77319f}
+component {b992ddcd-3899-4320-9909-924b3e72c922} FeedProcessor.js
+contract @mozilla.org/feed-textconstruct;1 {b992ddcd-3899-4320-9909-924b3e72c922}
+component {414af362-9ad8-4296-898e-62247f25a20e} FeedProcessor.js
+contract @mozilla.org/feed-generator;1 {414af362-9ad8-4296-898e-62247f25a20e}
+component {95c963b7-20b2-11db-92f6-001422106990} FeedProcessor.js
+contract @mozilla.org/feed-person;1 {95c963b7-20b2-11db-92f6-001422106990}
+component {26acb1f0-28fc-43bc-867a-a46aabc85dd4} FeedProcessor.js
+contract @mozilla.org/feed-processor;1 {26acb1f0-28fc-43bc-867a-a46aabc85dd4}
diff --git a/toolkit/components/feeds/moz.build b/toolkit/components/feeds/moz.build
new file mode 100644
index 000000000..de5e0aa96
--- /dev/null
+++ b/toolkit/components/feeds/moz.build
@@ -0,0 +1,31 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
+
+XPIDL_SOURCES += [
+ 'nsIFeed.idl',
+ 'nsIFeedContainer.idl',
+ 'nsIFeedElementBase.idl',
+ 'nsIFeedEntry.idl',
+ 'nsIFeedGenerator.idl',
+ 'nsIFeedListener.idl',
+ 'nsIFeedPerson.idl',
+ 'nsIFeedProcessor.idl',
+ 'nsIFeedResult.idl',
+ 'nsIFeedTextConstruct.idl',
+]
+
+XPIDL_MODULE = 'feeds'
+
+EXTRA_COMPONENTS += [
+ 'FeedProcessor.js',
+ 'FeedProcessor.manifest',
+]
+
+XPCSHELL_TESTS_MANIFESTS += [
+ 'test/xpcshell.ini'
+]
diff --git a/toolkit/components/feeds/nsIFeed.idl b/toolkit/components/feeds/nsIFeed.idl
new file mode 100644
index 000000000..ad87ad9d3
--- /dev/null
+++ b/toolkit/components/feeds/nsIFeed.idl
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "nsIFeedContainer.idl"
+
+interface nsIArray;
+interface nsIFeedGenerator;
+
+/**
+ * An nsIFeed represents a single Atom or RSS feed.
+ */
+[scriptable, uuid(3b8aae33-80e2-4efa-99c8-a6c5b99f76ea)]
+interface nsIFeed : nsIFeedContainer
+{
+ /**
+ * Uses description, subtitle, and extensions
+ * to generate a summary.
+ */
+ attribute nsIFeedTextConstruct subtitle;
+
+ // All content classifies as a "feed" - it is the transport.
+ const unsigned long TYPE_FEED = 0;
+ const unsigned long TYPE_AUDIO = 1;
+ const unsigned long TYPE_IMAGE = 2;
+ const unsigned long TYPE_VIDEO = 4;
+
+ /**
+ * The type of feed. For example, a podcast would be TYPE_AUDIO.
+ */
+ readonly attribute unsigned long type;
+
+ /**
+ * The total number of enclosures found in the feed.
+ */
+ attribute long enclosureCount;
+
+ /**
+ * The items or entries in feed.
+ */
+ attribute nsIArray items;
+
+ /**
+ * No one really knows what cloud is for.
+ *
+ * It supposedly enables some sort of interaction with an XML-RPC or
+ * SOAP service.
+ */
+ attribute nsIWritablePropertyBag2 cloud;
+
+ /**
+ * Information about the software that produced the feed.
+ */
+ attribute nsIFeedGenerator generator;
+
+ /**
+ * An image url and some metadata (as defined by RSS2).
+ *
+ */
+ attribute nsIWritablePropertyBag2 image;
+
+ /**
+ * No one really knows what textInput is for.
+ *
+ * See
+ * <http://www.cadenhead.org/workbench/news/2894/rss-joy-textinput>
+ * for more details.
+ */
+ attribute nsIWritablePropertyBag2 textInput;
+
+ /**
+ * Days to skip fetching. This field was supposed to designate
+ * intervals for feed fetching. It's not generally implemented. For
+ * example, if this array contained "Monday", aggregators should not
+ * fetch the feed on Mondays.
+ */
+ attribute nsIArray skipDays;
+
+ /**
+ * Hours to skip fetching. This field was supposed to designate
+ * intervals for feed fetching. It's not generally implemented. See
+ * <http://blogs.law.harvard.edu/tech/rss> for more information.
+ */
+ attribute nsIArray skipHours;
+};
diff --git a/toolkit/components/feeds/nsIFeedContainer.idl b/toolkit/components/feeds/nsIFeedContainer.idl
new file mode 100644
index 000000000..58de494a5
--- /dev/null
+++ b/toolkit/components/feeds/nsIFeedContainer.idl
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "nsIFeedElementBase.idl"
+
+interface nsIURI;
+interface nsIWritablePropertyBag2;
+interface nsIArray;
+interface nsIFeedTextConstruct;
+
+/**
+ * A shared base for feeds and items, which are pretty similar,
+ * but they have some divergent attributes and require
+ * different convenience methods.
+ */
+[scriptable, uuid(577a1b4c-b3d4-4c76-9cf8-753e6606114f)]
+interface nsIFeedContainer : nsIFeedElementBase
+{
+ /**
+ * Many feeds contain an ID distinct from their URI, and
+ * entries have standard fields for this in all major formats.
+ */
+ attribute AString id;
+
+ /**
+ * The fields found in the document. Common Atom
+ * and RSS fields are normalized. This includes some namespaced
+ * extensions such as dc:subject and content:encoded.
+ * Consumers can avoid normalization by checking the feed type
+ * and accessing specific fields.
+ *
+ * Common namespaces are accessed using prefixes, like get("dc:subject");.
+ * See nsIFeedResult::registerExtensionPrefix.
+ */
+ attribute nsIWritablePropertyBag2 fields;
+
+ /**
+ * Sometimes there's no title, or the title contains markup, so take
+ * care in decoding the attribute.
+ */
+ attribute nsIFeedTextConstruct title;
+
+ /**
+ * Returns the primary link for the feed or entry.
+ */
+ attribute nsIURI link;
+
+ /**
+ * Returns all links for a feed or entry.
+ */
+ attribute nsIArray links;
+
+ /**
+ * Returns the categories found in a feed or entry.
+ */
+ attribute nsIArray categories;
+
+ /**
+ * The rights or license associated with a feed or entry.
+ */
+ attribute nsIFeedTextConstruct rights;
+
+ /**
+ * A list of nsIFeedPersons that authored the feed.
+ */
+ attribute nsIArray authors;
+
+ /**
+ * A list of nsIFeedPersons that contributed to the feed.
+ */
+ attribute nsIArray contributors;
+
+ /**
+ * The date the feed was updated, in RFC822 form. Parsable by JS
+ * and mail code.
+ */
+ attribute AString updated;
+
+ /**
+ * Syncs a container's fields with its convenience attributes.
+ */
+ void normalize();
+};
diff --git a/toolkit/components/feeds/nsIFeedElementBase.idl b/toolkit/components/feeds/nsIFeedElementBase.idl
new file mode 100644
index 000000000..1b8975ae5
--- /dev/null
+++ b/toolkit/components/feeds/nsIFeedElementBase.idl
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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"
+
+interface nsISAXAttributes;
+interface nsIURI;
+
+/**
+ * An nsIFeedGenerator represents the software used to create a feed.
+ */
+[scriptable, uuid(5215291e-fa0a-40c2-8ce7-e86cd1a1d3fa)]
+interface nsIFeedElementBase : nsISupports
+{
+ /**
+ * The attributes found on the element. Most interfaces provide convenience
+ * accessors for their standard fields, so this useful only when looking for
+ * an extension.
+ */
+ attribute nsISAXAttributes attributes;
+
+ /**
+ * The baseURI for the Entry or Feed.
+ */
+ attribute nsIURI baseURI;
+};
diff --git a/toolkit/components/feeds/nsIFeedEntry.idl b/toolkit/components/feeds/nsIFeedEntry.idl
new file mode 100644
index 000000000..83646aadb
--- /dev/null
+++ b/toolkit/components/feeds/nsIFeedEntry.idl
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "nsIFeedContainer.idl"
+interface nsIArray;
+
+/**
+ * An nsIFeedEntry represents an Atom or RSS entry/item. Summary
+ * and/or full-text content may be available, but callers will have to
+ * check both.
+ */
+[scriptable, uuid(31bfd5b4-8ff5-4bfd-a8cb-b3dfbd4f0a5b)]
+interface nsIFeedEntry : nsIFeedContainer {
+
+ /**
+ * Uses description, subtitle, summary, content and extensions
+ * to generate a summary.
+ *
+ */
+ attribute nsIFeedTextConstruct summary;
+
+ /**
+ * The date the entry was published, in RFC822 form. Parsable by JS
+ * and mail code.
+ */
+ attribute AString published;
+
+ /**
+ * Uses atom:content and content:encoded to provide
+ * a 'full text' view of an entry.
+ *
+ */
+ attribute nsIFeedTextConstruct content;
+
+ /**
+ * Enclosures are podcasts, photocasts, etc.
+ */
+ attribute nsIArray enclosures;
+
+ /**
+ * Enclosures, etc. that might be displayed inline.
+ */
+ attribute nsIArray mediaContent;
+};
diff --git a/toolkit/components/feeds/nsIFeedGenerator.idl b/toolkit/components/feeds/nsIFeedGenerator.idl
new file mode 100644
index 000000000..3c23ca142
--- /dev/null
+++ b/toolkit/components/feeds/nsIFeedGenerator.idl
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "nsIFeedElementBase.idl"
+
+interface nsIURI;
+
+/**
+ * An nsIFeedGenerator represents the software used to create a feed.
+ */
+[scriptable, uuid(0fecd56b-bd92-481b-a486-b8d489cdd385)]
+interface nsIFeedGenerator : nsIFeedElementBase
+{
+ /**
+ * The name of the software.
+ */
+ attribute AString agent;
+
+ /**
+ * The version of the software.
+ */
+ attribute AString version;
+
+ /**
+ * A URI associated with the software.
+ */
+ attribute nsIURI uri;
+};
diff --git a/toolkit/components/feeds/nsIFeedListener.idl b/toolkit/components/feeds/nsIFeedListener.idl
new file mode 100644
index 000000000..6826d04a4
--- /dev/null
+++ b/toolkit/components/feeds/nsIFeedListener.idl
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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"
+interface nsIFeedResult;
+interface nsIFeedEntry;
+
+/**
+ * nsIFeedResultListener defines a callback used when feed processing
+ * completes.
+ */
+[scriptable, uuid(4d2ebe88-36eb-4e20-bcd1-997b3c1f24ce)]
+interface nsIFeedResultListener : nsISupports
+{
+ /**
+ * Always called, even after an error. There could be new feed-level
+ * data available at this point, if it followed or was interspersed
+ * with the items. Fire-and-Forget implementations only need this.
+ *
+ * @param result
+ * An object implementing nsIFeedResult representing the feed
+ * and its metadata.
+ */
+ void handleResult(in nsIFeedResult result);
+};
+
+
+/**
+ * nsIFeedProgressListener defines callbacks used during feed
+ * processing.
+ */
+[scriptable, uuid(ebfd5de5-713c-40c0-ad7c-f095117fa580)]
+interface nsIFeedProgressListener : nsIFeedResultListener {
+
+ /**
+ * ReportError will be called in the event of fatal
+ * XML errors, or if the document is not a feed. The bozo
+ * bit will be set if the error was due to a fatal error.
+ *
+ * @param errorText
+ * A short description of the error.
+ * @param lineNumber
+ * The line on which the error occurred.
+ */
+ void reportError(in AString errorText, in long lineNumber,
+ in boolean bozo);
+
+ /**
+ * StartFeed will be called as soon as a reasonable start to
+ * a feed is detected.
+ *
+ * @param result
+ * An object implementing nsIFeedResult representing the feed
+ * and its metadata. At this point, the result has version
+ * information.
+ */
+ void handleStartFeed(in nsIFeedResult result);
+
+ /**
+ * Called when the first entry/item is encountered. In Atom, all
+ * feed data is required to preceed the entries. In RSS, the data
+ * usually does. If the type is one of the entry/item-only types,
+ * this event will not be called.
+ *
+ * @param result
+ * An object implementing nsIFeedResult representing the feed
+ * and its metadata. At this point, the result will likely have
+ * most of its feed-level metadata.
+ */
+ void handleFeedAtFirstEntry(in nsIFeedResult result);
+
+ /**
+ * Called after each entry/item. If the document is a standalone
+ * item or entry, this HandleFeedAtFirstEntry will not have been
+ * called. Also, this entry's parent field will be null.
+ *
+ * @param entry
+ * An object implementing nsIFeedEntry that represents the latest
+ * entry encountered.
+ * @param result
+ * An object implementing nsIFeedResult representing the feed
+ * and its metadata.
+ */
+ void handleEntry(in nsIFeedEntry entry, in nsIFeedResult result);
+};
diff --git a/toolkit/components/feeds/nsIFeedPerson.idl b/toolkit/components/feeds/nsIFeedPerson.idl
new file mode 100644
index 000000000..d9d6eb77b
--- /dev/null
+++ b/toolkit/components/feeds/nsIFeedPerson.idl
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "nsIFeedElementBase.idl"
+
+interface nsIURI;
+
+/**
+ * An nsIFeedPerson represents an author or contributor of a feed.
+ */
+[scriptable, uuid(29cbd45f-f2d3-4b28-b557-3ab7a61ecde4)]
+interface nsIFeedPerson : nsIFeedElementBase
+{
+ /**
+ * The name of the person.
+ */
+ attribute AString name;
+
+ /**
+ * An email address associated with the person.
+ */
+ attribute AString email;
+
+ /**
+ * A URI associated with the person (e.g. a homepage).
+ */
+ attribute nsIURI uri;
+};
diff --git a/toolkit/components/feeds/nsIFeedProcessor.idl b/toolkit/components/feeds/nsIFeedProcessor.idl
new file mode 100644
index 000000000..d7205600d
--- /dev/null
+++ b/toolkit/components/feeds/nsIFeedProcessor.idl
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "nsIStreamListener.idl"
+
+interface nsIURI;
+interface nsIFeedResultListener;
+interface nsIInputStream;
+
+/**
+ * An nsIFeedProcessor parses feeds, triggering callbacks based on
+ * their contents.
+ */
+[scriptable, uuid(8a0b2908-21b0-45d7-b14d-30df0f92afc7)]
+interface nsIFeedProcessor : nsIStreamListener {
+
+ /**
+ * The listener that will respond to feed events.
+ */
+ attribute nsIFeedResultListener listener;
+
+ // Level is where to listen for the extension, a constant: FEED,
+ // ENTRY, BOTH.
+ //
+ // XXX todo void registerExtensionHandler(in
+ // nsIFeedExtensionHandler, in long level);
+
+ /**
+ * Parse a feed from an nsIInputStream.
+ *
+ * @param stream The input stream.
+ * @param uri The base URI.
+ */
+ void parseFromStream(in nsIInputStream stream, in nsIURI uri);
+
+ /**
+ * Parse a feed from a string.
+ *
+ * @param str The string to parse.
+ * @param uri The base URI.
+ */
+ void parseFromString(in AString str, in nsIURI uri);
+
+ /**
+ * Parse a feed asynchronously. The caller must then call the
+ * nsIFeedProcessor's nsIStreamListener methods to drive the
+ * parse. Do not call the other parse methods during an asynchronous
+ * parse.
+ *
+ * @param requestObserver The observer to notify on start/stop. This
+ * argument can be null.
+ * @param uri The base URI.
+ */
+ void parseAsync(in nsIRequestObserver requestObserver, in nsIURI uri);
+};
diff --git a/toolkit/components/feeds/nsIFeedResult.idl b/toolkit/components/feeds/nsIFeedResult.idl
new file mode 100644
index 000000000..4cfb0a13e
--- /dev/null
+++ b/toolkit/components/feeds/nsIFeedResult.idl
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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"
+interface nsIFeedContainer;
+interface nsIProperties;
+interface nsIURI;
+
+/**
+ * The nsIFeedResult interface provides access to HTTP and parsing
+ * metadata for a feed or entry.
+ */
+[scriptable, uuid(7a180b78-0f46-4569-8c22-f3d720ea1c57)]
+interface nsIFeedResult : nsISupports {
+
+ /**
+ * The Feed parser will set the bozo bit when a feed triggers a fatal
+ * error during XML parsing. There may be entries and feed metadata
+ * that were parsed before the error. Thanks to Tim Bray for
+ * suggesting this terminology.
+ * <http://www.tbray.org/ongoing/When/200x/2004/01/11/PostelPilgrim>
+ */
+ attribute boolean bozo;
+
+ /**
+ * The parsed feed or entry.
+ *
+ * Will be null if a non-feed is processed.
+ */
+ attribute nsIFeedContainer doc;
+
+ /**
+ * The address from which the feed was fetched.
+ */
+ attribute nsIURI uri;
+
+ /**
+ * Feed Version:
+ * atom, rss2, rss09, rss091, rss091userland, rss092, rss1, atom03,
+ * atomEntry, rssItem
+ *
+ * Will be null if a non-feed is processed.
+ */
+ attribute AString version;
+
+ /**
+ * An XSLT stylesheet available to transform the source of the
+ * feed. Some feeds include this information in a processing
+ * instruction. It's generally intended for clients with specific
+ * feed capabilities.
+ */
+ attribute nsIURI stylesheet;
+
+ /**
+ * HTTP response headers that accompanied the feed.
+ */
+ attribute nsIProperties headers;
+
+ /**
+ * Registers a prefix used to access an extension in the feed/entry
+ */
+ void registerExtensionPrefix(in AString aNamespace, in AString aPrefix);
+};
diff --git a/toolkit/components/feeds/nsIFeedTextConstruct.idl b/toolkit/components/feeds/nsIFeedTextConstruct.idl
new file mode 100644
index 000000000..070acb20a
--- /dev/null
+++ b/toolkit/components/feeds/nsIFeedTextConstruct.idl
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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"
+
+interface nsIURI;
+interface nsIDOMElement;
+interface nsIDOMDocumentFragment;
+
+/**
+ * nsIFeedTextConstructs represent feed text fields that can contain
+ * one of text, HTML, or XHTML. Some extension elements also have "type"
+ * parameters, and this interface could be used there as well.
+ */
+[scriptable, uuid(fc97a2a9-d649-4494-931e-db81a156c873)]
+interface nsIFeedTextConstruct : nsISupports
+{
+ /**
+ * If the text construct contains (X)HTML, relative references in
+ * the content should be resolved against this base URI.
+ */
+ attribute nsIURI base;
+
+ /**
+ * The language of the text. For example, "en-US" for US English.
+ */
+ attribute AString lang;
+
+ /**
+ * One of "text", "html", or "xhtml". If the type is (x)html, a '<'
+ * character represents markup. To display that character, an escape
+ * such as &lt; must be used. If the type is "text", the '<'
+ * character represents the character itself, and such text should
+ * not be embedded in markup without escaping it first.
+ */
+ attribute AString type;
+
+ /**
+ * The content of the text construct.
+ */
+ attribute AString text;
+
+ /**
+ * Returns the text of the text construct, with all markup stripped
+ * and all entities decoded. If the type attribute's value is "text",
+ * this function returns the value of the text attribute unchanged.
+ */
+ AString plainText();
+
+ /**
+ * Return an nsIDocumentFragment containing the text and markup.
+ */
+ nsIDOMDocumentFragment createDocumentFragment(in nsIDOMElement element);
+};
+
diff --git a/toolkit/components/feeds/test/.eslintrc.js b/toolkit/components/feeds/test/.eslintrc.js
new file mode 100644
index 000000000..89764b551
--- /dev/null
+++ b/toolkit/components/feeds/test/.eslintrc.js
@@ -0,0 +1,8 @@
+"use strict";
+
+module.exports = {
+ "extends": [
+ "../../../../testing/mochitest/chrome.eslintrc.js",
+ "../../../../testing/xpcshell/xpcshell.eslintrc.js"
+ ]
+};
diff --git a/toolkit/components/feeds/test/chrome.ini b/toolkit/components/feeds/test/chrome.ini
new file mode 100644
index 000000000..6745fa9a5
--- /dev/null
+++ b/toolkit/components/feeds/test/chrome.ini
@@ -0,0 +1,3 @@
+[DEFAULT]
+
+[test_bug675492.xul]
diff --git a/toolkit/components/feeds/test/head.js b/toolkit/components/feeds/test/head.js
new file mode 100644
index 000000000..65aa64b94
--- /dev/null
+++ b/toolkit/components/feeds/test/head.js
@@ -0,0 +1,80 @@
+"use strict";
+
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+var Cu = Components.utils;
+var Cr = Components.results;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/NetUtil.jsm");
+
+function readTestData(testFile) {
+ var testcase = {};
+
+ // Got a feed file, now we need to parse out the Description and Expect headers.
+ var istream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
+ try {
+ istream.init(testFile, 0x01, parseInt("0444", 8), 0);
+ istream.QueryInterface(Ci.nsILineInputStream);
+
+ var hasmore = false;
+ do {
+ var line = {};
+ hasmore = istream.readLine(line);
+
+ if (line.value.indexOf('Description:') > -1) {
+ testcase.desc = line.value.substring(line.value.indexOf(':')+1).trim();
+ }
+
+ if (line.value.indexOf('Expect:') > -1) {
+ testcase.expect = line.value.substring(line.value.indexOf(':')+1).trim();
+ }
+
+ if (line.value.indexOf('Base:') > -1) {
+ testcase.base = NetUtil.newURI(line.value.substring(line.value.indexOf(':')+1).trim());
+ }
+
+ if (testcase.expect && testcase.desc) {
+ testcase.path = 'xml/' + testFile.parent.leafName + '/' + testFile.leafName;
+ testcase.file = testFile;
+ break;
+ }
+
+ } while (hasmore);
+
+ } catch (e) {
+ Assert.ok(false, "FAILED! Error reading testFile case in file " + testFile.leafName + " ---- " + e);
+ } finally {
+ istream.close();
+ }
+
+ return testcase;
+}
+
+function iterateDir(dir, recurse, callback) {
+ do_print("Iterate " + dir.leafName);
+ let entries = dir.directoryEntries;
+
+ // Loop over everything in this dir. If its a dir
+ while (entries.hasMoreElements()) {
+ let entry = entries.getNext();
+ entry.QueryInterface(Ci.nsILocalFile);
+
+ if (entry.isDirectory()) {
+ if (recurse) {
+ iterateDir(entry, recurse, callback);
+ }
+ } else {
+ callback(entry);
+ }
+ }
+}
+
+function isIID(a, iid) {
+ try {
+ a.QueryInterface(iid);
+ return true;
+ } catch (e) { }
+
+ return false;
+}
diff --git a/toolkit/components/feeds/test/test_bug675492.xul b/toolkit/components/feeds/test/test_bug675492.xul
new file mode 100644
index 000000000..b1c52d11a
--- /dev/null
+++ b/toolkit/components/feeds/test/test_bug675492.xul
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=675492
+-->
+<window title="Mozilla Bug 675492"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+ <script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"/>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=675492"
+ target="_blank">Mozilla Bug 675492</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ /** Test for Bug 675492 **/
+
+ Components
+ .classes["@mozilla.org/parserutils;1"]
+ .getService(Components.interfaces.nsIParserUtils)
+ .parseFragment("<p>test</p>", 0, false, null, document.createElementNS("http://www.w3.org/1999/xhtml", "body"));
+ ok(true, "No crash!");
+ ]]>
+ </script>
+</window>
diff --git a/toolkit/components/feeds/test/test_xml.js b/toolkit/components/feeds/test/test_xml.js
new file mode 100644
index 000000000..5bc0d759d
--- /dev/null
+++ b/toolkit/components/feeds/test/test_xml.js
@@ -0,0 +1,97 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
+ * 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/. */
+
+/* test_xml.js
+ * This file sets up the unit test environment by building an array of files
+ * to be tested. It assumes it lives in a folder adjacent to the a folder
+ * called 'xml', where the testcases live.
+ *
+ * The directory layout looks something like this:
+ *
+ * tests/test_xml.js*
+ * |
+ * - head.js
+ * |
+ * - xml/ -- rss1/...
+ * |
+ * -- rss2/...
+ * |
+ * -- atom/testcase.xml
+ *
+ * To add more tests, just include the file in the xml subfolder and add its name to xpcshell.ini
+ */
+
+"use strict";
+
+// Listens to feeds being loaded. Runs the tests built into the feed afterwards to veryify they
+// were parsed correctly.
+function FeedListener(testcase) {
+ this.testcase = testcase;
+}
+
+FeedListener.prototype = {
+ handleResult: function(result) {
+ var feed = result.doc;
+ try {
+ do_print("Testing feed " + this.testcase.file.path);
+ Assert.ok(isIID(feed, Ci.nsIFeed), "Has feed interface");
+
+ if (!eval(this.testcase.expect)) {
+ Assert.ok(false, "expect failed for " + this.testcase.desc);
+ } else {
+ Assert.ok(true, "expect passed for " + this.testcase.desc);
+ }
+ } catch (e) {
+ Assert.ok(false, "expect failed for " + this.testcase.desc + " ---- " + e.message);
+ }
+
+ run_next_test();
+ }
+}
+
+function createTest(data) {
+ return function() {
+ var uri;
+
+ if (data.base == null) {
+ uri = NetUtil.newURI('http://example.org/' + data.path);
+ } else {
+ uri = data.base;
+ }
+
+ do_print("Testing " + data.file.leafName);
+
+ var parser = Cc["@mozilla.org/feed-processor;1"].createInstance(Ci.nsIFeedProcessor);
+ var stream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
+ stream.init(data.file, 0x01, parseInt("0444", 8), 0);
+ parser.listener = new FeedListener(data);
+
+ try {
+ parser.parseFromStream(stream, uri);
+ } catch (e) {
+ Assert.ok(false, "parse failed for " + data.file.leafName + " ---- " + e.message);
+ // If the parser failed, the listener won't be notified, run the next test here.
+ run_next_test();
+ } finally {
+ stream.close();
+ }
+ }
+}
+
+function run_test() {
+ // Get the 'xml' directory in here
+ var topDir = Services.dirsvc.get("CurWorkD", Ci.nsIFile);
+ topDir.append("xml");
+
+ // Every file in the test dir contains an encapulated RSS "test". Iterate through
+ // them all and add them to the test runner.
+ iterateDir(topDir, true, file => {
+ var data = readTestData(file);
+ add_test(createTest(data));
+ });
+
+ // Now run!
+ run_next_test();
+}
diff --git a/toolkit/components/feeds/test/xml/rfc4287/author_namespaces.xml b/toolkit/components/feeds/test/xml/rfc4287/author_namespaces.xml
new file mode 100644
index 000000000..3b2ad74ff
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/author_namespaces.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Description: Ensure unknown NS element in atom:author doesn't cause exception
+Expect: var mCService = Components.classes['@mozilla.org/consoleservice;1'].getService(Components.interfaces.nsIConsoleService); var msg = mCService.getMessageArray()[0]; if(msg){msg = msg.message}; ((msg + "").indexOf("prefix has no properties") == -1);
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+
+ <author>
+ <name>Sam Ruby</name>
+ <method xmlns="http://www.intertwingly.net/blog/">excerpt</method>
+ <email>rubys@intertwingly.net</email>
+ <uri>.</uri>
+ </author>
+
+</feed>
+
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_author.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_author.xml
new file mode 100644
index 000000000..2757148c4
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_author.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom author name works
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).authors.queryElementAt(0, Components.interfaces.nsIFeedPerson).name=='John Doe Entry';
+
+-->
+
+<feed xmlns="http://www.w3.org/2005/Atom">
+
+ <title>Example Feed</title>
+ <link href="http://example.org/"/>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <author>
+ <name>John Doe</name>
+ </author>
+ <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+
+ <entry>
+ <title>Atom-Powered Robots Run Amok</title>
+ <link href="http://example.org/2003/12/13/atom03"/>
+ <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <summary>Some text.</summary>
+ <author>
+ <name>John Doe Entry</name>
+ </author>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_content.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_content.xml
new file mode 100644
index 000000000..6bb9b210f
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_content.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry summary works
+Expect: feed.items.queryElementAt(1, Components.interfaces.nsIFeedEntry).content.plainText() == "test content";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:foo="http://www.example.org"
+ foo:quux="quuux">
+
+ <title>hmm</title>
+
+ <author>
+ <email>hmm@example.com</email>
+ <name>foo</name>
+ </author>
+ <generator version="1.1" uri="http://example.org">Hmm</generator>
+ <author>
+ <email>bar@example.com</email>
+ <name>foo</name>
+ </author>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><i>test</i> rights</div>
+ </rights>
+
+
+ <entry></entry>
+
+ <entry foo:bar="baz">
+ <title>test</title>
+ <content>test content</content>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_content_encoded.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_content_encoded.xml
new file mode 100644
index 000000000..df09317f7
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_content_encoded.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry content:encoded and xhtml works
+Expect: var content = feed.items.queryElementAt(1, Components.interfaces.nsIFeedEntry).content.plainText(); content == "should appear";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:foo="http://www.example.org"
+ foo:quux="quuux"
+ xmlns:content="http://purl.org/rss/1.0/modules/content/">
+
+ <title>hmm</title>
+
+ <author>
+ <email>hmm@example.com</email>
+ <name>foo</name>
+ </author>
+ <generator version="1.1" uri="http://example.org">Hmm</generator>
+ <author>
+ <email>bar@example.com</email>
+ <name>foo</name>
+ </author>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><i>test</i> rights</div>
+ </rights>
+
+
+ <entry></entry>
+
+ <entry foo:bar="baz">
+ <title>test</title>
+ <summary type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml">
+ <b>test</b> content
+ </div>
+ </summary>
+ <content:encoded>
+ should appear
+ </content:encoded>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_content_html.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_content_html.xml
new file mode 100644
index 000000000..08974c35f
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_content_html.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry content html works
+Expect: var content = feed.items.queryElementAt(1, Components.interfaces.nsIFeedEntry).content.plainText(); content == "test content";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:foo="http://www.example.org"
+ foo:quux="quuux">
+
+ <title>hmm</title>
+
+ <author>
+ <email>hmm@example.com</email>
+ <name>foo</name>
+ </author>
+ <generator version="1.1" uri="http://example.org">Hmm</generator>
+ <author>
+ <email>bar@example.com</email>
+ <name>foo</name>
+ </author>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><i>test</i> rights</div>
+ </rights>
+
+
+ <entry></entry>
+
+ <entry foo:bar="baz">
+ <title>test</title>
+ <content type="html">&lt;b>test&lt;/b> content</content>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_content_xhtml.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_content_xhtml.xml
new file mode 100644
index 000000000..dea4902bb
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_content_xhtml.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry content xhtml works
+Expect: feed.items.queryElementAt(1, Components.interfaces.nsIFeedEntry).content.plainText() == "test content";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:foo="http://www.example.org"
+ foo:quux="quuux">
+
+ <title>hmm</title>
+
+ <author>
+ <email>hmm@example.com</email>
+ <name>foo</name>
+ </author>
+ <generator version="1.1" uri="http://example.org">Hmm</generator>
+ <author>
+ <email>bar@example.com</email>
+ <name>foo</name>
+ </author>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><i>test</i> rights</div>
+ </rights>
+
+
+ <entry></entry>
+
+ <entry foo:bar="baz">
+ <title>test</title>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml">
+ <b>test</b> content
+ </div>
+ </content>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_content_xhtml_with_markup.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_content_xhtml_with_markup.xml
new file mode 100644
index 000000000..8cadef75e
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_content_xhtml_with_markup.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry content xhtml works
+Expect: var content = feed.items.queryElementAt(1, Components.interfaces.nsIFeedEntry).content.text; content == "<b>test</b> content";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:foo="http://www.example.org"
+ foo:quux="quuux">
+
+ <title>hmm</title>
+
+ <author>
+ <email>hmm@example.com</email>
+ <name>foo</name>
+ </author>
+ <generator version="1.1" uri="http://example.org">Hmm</generator>
+ <author>
+ <email>bar@example.com</email>
+ <name>foo</name>
+ </author>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><i>test</i> rights</div>
+ </rights>
+
+
+ <entry></entry>
+
+ <entry foo:bar="baz">
+ <title>test</title>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml">
+ <b>test</b> content
+ </div>
+ </content>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_contributor.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_contributor.xml
new file mode 100644
index 000000000..bb85bf230
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_contributor.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom author name works
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).contributors.queryElementAt(0, Components.interfaces.nsIFeedPerson).name=='John Doe Entry';
+
+-->
+
+<feed xmlns="http://www.w3.org/2005/Atom">
+
+ <title>Example Feed</title>
+ <link href="http://example.org/"/>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <author>
+ <name>John Doe</name>
+ </author>
+ <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+
+ <entry>
+ <title>Atom-Powered Robots Run Amok</title>
+ <link href="http://example.org/2003/12/13/atom03"/>
+ <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <summary>Some text.</summary>
+ <contributor>
+ <name>John Doe Entry</name>
+ </contributor>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_html_cdata.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_html_cdata.xml
new file mode 100644
index 000000000..38a31ca10
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_html_cdata.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: HTML title w/ CDATA
+Expect: var title = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).title.plainText(); title == "<title>";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+<id>http://atomtests.philringnalda.com/tests/item/title/html-cdata.atom</id>
+<title>Atom item title html cdata</title>
+<updated>2005-12-18T00:13:00Z</updated>
+<author>
+ <name>Phil Ringnalda</name>
+ <uri>http://weblog.philringnalda.com/</uri>
+</author>
+<link rel="self" href="http://atomtests.philringnalda.com/tests/item/title/html-cdata.atom"/>
+<entry>
+ <id>http://atomtests.philringnalda.com/tests/item/title/html-cdata.atom/1</id>
+ <title type="html"><![CDATA[&lt;title>]]></title>
+ <updated>2005-12-18T00:13:00Z</updated>
+ <summary>An item with a type="html" title consisting of a less-than
+character, the word 'title' and a greater-than character, where
+the character entity reference for the less-than is escaped by being
+in a CDATA section.</summary>
+ <link href="http://atomtests.philringnalda.com/alt/title-title.html"/>
+ <category term="item title"/>
+</entry>
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_id.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_id.xml
new file mode 100644
index 000000000..8513b6894
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_id.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry id
+Expect: feed.items.queryElementAt(1, Components.interfaces.nsIFeedEntry).id == "http://foo.example.com/hmm/ok,2006,07,11";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:foo="http://www.example.org"
+ foo:quux="quuux">
+
+ <title>hmm</title>
+
+ <author>
+ <email>hmm@example.com</email>
+ <name>foo</name>
+ </author>
+ <generator version="1.1" uri="http://example.org">Hmm</generator>
+ <author>
+ <email>bar@example.com</email>
+ <name>foo</name>
+ </author>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><i>test</i> rights</div>
+ </rights>
+
+
+ <entry></entry>
+
+ <entry foo:bar="baz">
+ <title>test</title>
+ <id>http://foo.example.com/hmm/ok,2006,07,11</id>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_link_2alts.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_link_2alts.xml
new file mode 100644
index 000000000..c7cebe4cd
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_link_2alts.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry with random link relations
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link.spec == "http://www.snellspace.com/public/linktests/alternate";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <id>tag:snellspace.com,2006:/atom/conformance/linktest/</id>
+ <title>Atom Link Tests</title>
+ <updated>2005-01-18T15:10:00Z</updated>
+ <author><name>James Snell</name></author>
+ <link href="http://www.intertwingly.net/wiki/pie/LinkConformanceTests" />
+ <link rel="self" href="http://www.snellspace.com/public/linktests.xml" />
+
+ <entry>
+ <id>tag:snellspace.com,2006:/atom/conformance/linktest/2</id>
+ <title>Two alternate links</title>
+ <updated>2005-01-18T15:00:02Z</updated>
+ <summary>The aggregator should pick either the second or third link below as the alternate</summary>
+
+ <link rel="ALTERNATE" href="http://www.snellspace.com/public/linktests/wrong" />
+ <link href="http://www.snellspace.com/public/linktests/alternate" />
+ <link type="text/plain" href="http://www.snellspace.com/public/linktests/alternate2" />
+ <link rel="ALTERNATE" href="http://www.snellspace.com/public/linktests/wrong" />
+ </entry>
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_link_2alts_allcore.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_link_2alts_allcore.xml
new file mode 100644
index 000000000..56675b1a9
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_link_2alts_allcore.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry with random link relations
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link.spec == "http://www.snellspace.com/public/linktests/alternate";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <id>tag:snellspace.com,2006:/atom/conformance/linktest/</id>
+ <title>Atom Link Tests</title>
+ <updated>2005-01-18T15:10:00Z</updated>
+ <author><name>James Snell</name></author>
+ <link href="http://www.intertwingly.net/wiki/pie/LinkConformanceTests" />
+ <link rel="self" href="http://www.snellspace.com/public/linktests.xml" />
+
+ <entry>
+ <id>tag:snellspace.com,2006:/atom/conformance/linktest/3</id>
+ <title>One of each core link rel type</title>
+
+ <updated>2005-01-18T15:00:03Z</updated>
+ <summary>The aggregator should pick the first link as the alternate</summary>
+ <link href="http://www.snellspace.com/public/linktests/alternate" />
+ <link rel="enclosure" href="http://www.snellspace.com/public/linktests/enclosure" length="19" />
+ <link rel="related" href="http://www.snellspace.com/public/linktests/related" />
+ <link rel="self" href="http://www.snellspace.com/public/linktests/self" />
+ <link rel="via" href="http://www.snellspace.com/public/linktests/via" />
+ </entry>
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_link_2alts_allcore2.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_link_2alts_allcore2.xml
new file mode 100644
index 000000000..b5b73cfe0
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_link_2alts_allcore2.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry with random link relations
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link.spec == "http://www.snellspace.com/public/linktests/alternate";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <id>tag:snellspace.com,2006:/atom/conformance/linktest/</id>
+ <title>Atom Link Tests</title>
+ <updated>2005-01-18T15:10:00Z</updated>
+ <author><name>James Snell</name></author>
+ <link href="http://www.intertwingly.net/wiki/pie/LinkConformanceTests" />
+ <link rel="self" href="http://www.snellspace.com/public/linktests.xml" />
+
+
+
+ <entry>
+
+ <id>tag:snellspace.com,2006:/atom/conformance/linktest/4</id>
+ <title>One of each core link rel type + An additional alternate link</title>
+ <updated>2005-01-18T15:00:04Z</updated>
+ <summary>The aggregator should pick either the first or last links as the alternate. First link is likely better.</summary>
+ <link href="http://www.snellspace.com/public/linktests/alternate" />
+ <link rel="enclosure" href="http://www.snellspace.com/public/linktests/enclosure" length="19" />
+ <link rel="related" href="http://www.snellspace.com/public/linktests/related" />
+
+ <link rel="self" href="http://www.snellspace.com/public/linktests/self" />
+ <link rel="via" href="http://www.snellspace.com/public/linktests/via" />
+ <link rel="alternate" type="text/plain" href="http://www.snellspace.com/public/linktests/alternate2" />
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_link_IANA.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_link_IANA.xml
new file mode 100644
index 000000000..af6563f2e
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_link_IANA.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry with IANA URI link relations
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link.spec == "http://www.snellspace.com/public/alternate";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <id>tag:snellspace.com,2006:/atom/conformance/linktest/</id>
+ <title>Atom Link Tests</title>
+ <updated>2005-01-18T15:10:00Z</updated>
+ <author><name>James Snell</name></author>
+ <link href="http://www.intertwingly.net/wiki/pie/LinkConformanceTests" />
+ <link rel="self" href="http://www.snellspace.com/public/linktests.xml" />
+
+ <entry>
+ <id>tag:example.org,2006:/linkreltest/1</id>
+ <title>Does your reader support http://www.iana.org/assignments/relation/alternate properly? </title>
+ <updated>2006-04-25T12:12:12Z</updated>
+ <link rel="http://example.org/random"
+ href="http://www.snellspace.com/public/random" />
+ <link rel="http://www.iana.org/assignments/relation/alternate"
+ href="http://www.snellspace.com/public/alternate" />
+ <link rel="http://example.org/random"
+ href="http://www.snellspace.com/public/random" />
+ <content>This entry uses link/@rel="http://www.iana.org/assignments/relation/alternate".</content>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_link_alt_extension.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_link_alt_extension.xml
new file mode 100644
index 000000000..e37421864
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_link_alt_extension.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry with random link relations
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link.spec == "http://www.snellspace.com/public/linktests/alternate";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <id>tag:snellspace.com,2006:/atom/conformance/linktest/</id>
+ <title>Atom Link Tests</title>
+ <updated>2005-01-18T15:10:00Z</updated>
+ <author><name>James Snell</name></author>
+ <link href="http://www.intertwingly.net/wiki/pie/LinkConformanceTests" />
+ <link rel="self" href="http://www.snellspace.com/public/linktests.xml" />
+ <entry>
+ <id>tag:snellspace.com,2006:/atom/conformance/linktest/5</id>
+ <title>Entry with a link relation registered by an extension</title>
+ <updated>2005-01-18T15:00:05Z</updated>
+ <summary>The aggregator should ignore the license link without throwing any errors. The first link should be picked as the alternate.</summary>
+ <link href="http://www.snellspace.com/public/linktests/alternate" />
+ <link rel="payment" href="http://www.example.org/payment" />
+ </entry>
+
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_link_enclosure.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_link_enclosure.xml
new file mode 100644
index 000000000..b76c111c9
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_link_enclosure.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item enclosure works
+Expect: var links = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).fields.getProperty('links'); links.QueryInterface(Components.interfaces.nsIArray); var link = links.queryElementAt(0, Components.interfaces.nsIPropertyBag2); ((link.getProperty('length') == '24986239') && (link.getProperty('type') == 'audio/mpeg') && (link.getProperty('href') == 'http://dallas.example.com/joebob_050689.mp3') && (feed.type == 1) && (feed.enclosureCount == 1));
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <id>tag:snellspace.com,2006:/atom/conformance/linktest/</id>
+ <title>Atom Link Tests</title>
+ <updated>2005-01-18T15:10:00Z</updated>
+ <author><name>James Snell</name></author>
+ <link href="http://www.intertwingly.net/wiki/pie/LinkConformanceTests" />
+ <link rel="self" href="http://www.snellspace.com/public/linktests.xml" />
+
+
+
+ <entry>
+
+ <id>tag:snellspace.com,2006:/atom/conformance/linktest/4</id>
+ <title>One of each core link rel type + An additional alternate link</title>
+ <updated>2005-01-18T15:00:04Z</updated>
+ <summary>The aggregator should pick either the first or last links as the alternate. First link is likely better.</summary>
+ <link rel="enclosure" length="24986239" type="audio/mpeg" href="http://dallas.example.com/joebob_050689.mp3" />
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_link_enclosure_populate_enclosures.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_link_enclosure_populate_enclosures.xml
new file mode 100644
index 000000000..8453c6e9c
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_link_enclosure_populate_enclosures.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item enclosure added to enclosures
+Expect: var encs = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).enclosures; encs.QueryInterface(Components.interfaces.nsIArray); var enc = encs.queryElementAt(0, Components.interfaces.nsIPropertyBag2); ((enc.getProperty('length') == '24986239') && (enc.getProperty('type') == 'audio/mpeg') && (enc.getProperty('url') == 'http://dallas.example.com/joebob_050689.mp3'));
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <id>tag:snellspace.com,2006:/atom/conformance/linktest/</id>
+ <title>Atom Link Tests</title>
+ <updated>2005-01-18T15:10:00Z</updated>
+ <author><name>James Snell</name></author>
+ <link href="http://www.intertwingly.net/wiki/pie/LinkConformanceTests" />
+ <link rel="self" href="http://www.snellspace.com/public/linktests.xml" />
+
+
+
+ <entry>
+
+ <id>tag:snellspace.com,2006:/atom/conformance/linktest/4</id>
+ <title>One of each core link rel type + An additional alternate link</title>
+ <updated>2005-01-18T15:00:04Z</updated>
+ <summary>The aggregator should pick either the first or last links as the alternate. First link is likely better.</summary>
+ <link rel="enclosure" length="24986239" type="audio/mpeg" href="http://dallas.example.com/joebob_050689.mp3" />
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_link_otherURI_alt.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_link_otherURI_alt.xml
new file mode 100644
index 000000000..3dc0c8dd6
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_link_otherURI_alt.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry with random link relations
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link.spec == "http://www.snellspace.com/public/linktests/alternate";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <id>tag:snellspace.com,2006:/atom/conformance/linktest/</id>
+ <title>Atom Link Tests</title>
+ <updated>2005-01-18T15:10:00Z</updated>
+ <author><name>James Snell</name></author>
+ <link href="http://www.intertwingly.net/wiki/pie/LinkConformanceTests" />
+ <link rel="self" href="http://www.snellspace.com/public/linktests.xml" />
+
+ <entry>
+ <id>tag:snellspace.com,2006:/atom/conformance/linktest/6</id>
+ <title>Entry with a link relation identified by URI</title>
+ <updated>2005-01-18T15:00:06Z</updated>
+ <summary>The aggregator should ignore the second link without throwing any errors. The first link should be picked as the alternate.</summary>
+ <link href="http://www.snellspace.com/public/linktests/alternate" />
+ <link rel="http://example.org" href="http://www.snellspace.com/public/linktests/example" />
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_link_payment_alt.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_link_payment_alt.xml
new file mode 100644
index 000000000..51e1524b4
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_link_payment_alt.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry with random link relations
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link.spec == "http://www.snellspace.com/public/linktests/alternate";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <id>tag:snellspace.com,2006:/atom/conformance/linktest/</id>
+ <title>Atom Link Tests</title>
+ <updated>2005-01-18T15:10:00Z</updated>
+ <author><name>James Snell</name></author>
+ <link href="http://www.intertwingly.net/wiki/pie/LinkConformanceTests" />
+ <link rel="self" href="http://www.snellspace.com/public/linktests.xml" />
+
+
+ <entry>
+ <id>tag:snellspace.com,2006:/atom/conformance/linktest/5</id>
+ <title>Entry with a link relation registered by an extension</title>
+ <updated>2005-01-18T15:00:05Z</updated>
+ <summary>The aggregator should ignore the license link without throwing any errors. The first link should be picked as the alternate.</summary>
+ <link href="http://www.snellspace.com/public/linktests/alternate" />
+ <link rel="payment" href="http://www.example.org/payment" />
+ </entry>
+
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_link_random.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_link_random.xml
new file mode 100644
index 000000000..cb370e516
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_link_random.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry with random link relations
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link.spec == "http://www.snellspace.com/public/linktests/alternate";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <id>tag:snellspace.com,2006:/atom/conformance/linktest/</id>
+ <title>Atom Link Tests</title>
+ <updated>2005-01-18T15:10:00Z</updated>
+ <author><name>James Snell</name></author>
+ <link href="http://www.intertwingly.net/wiki/pie/LinkConformanceTests" />
+ <link rel="self" href="http://www.snellspace.com/public/linktests.xml" />
+
+ <entry>
+ <id>tag:snellspace.com,2006:/atom/conformance/linktest/1</id>
+ <title>Just a single Alternate Link</title>
+ <updated>2005-01-18T15:00:01Z</updated>
+ <summary>The aggregator should pick the second link as the alternate</summary>
+ <link rel="http://example.org/random"
+ href="http://www.snellspace.com/public/wrong" />
+ <link href="http://www.snellspace.com/public/linktests/alternate" />
+ <link rel="http://example.org/random"
+ href="http://www.snellspace.com/public/wrong" />
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_published.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_published.xml
new file mode 100644
index 000000000..1112729e2
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_published.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom published works
+Expect: var entry = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry); entry.published == 'Tue, 09 Dec 2003 18:30:02 GMT'
+
+-->
+
+<feed xmlns="http://www.w3.org/2005/Atom">
+
+ <title>Example Feed</title>
+ <link href="http://example.org/"/>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <author>
+ <name>John Doe</name>
+ </author>
+ <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+
+ <entry>
+ <title>Atom-Powered Robots Run Amok</title>
+ <link href="http://example.org/2003/12/13/atom03"/>
+ <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <published>2003-12-09T18:30:02Z</published>
+ <summary>Some text.</summary>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_rights_normalized.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_rights_normalized.xml
new file mode 100644
index 000000000..1474e5f84
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_rights_normalized.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry rights works normalized
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).rights.plainText() == "test rights"
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <title type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><b>test</b> title</div>
+ </title>
+ <entry>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><b>test</b> rights</div>
+ </rights>
+ </entry>
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_summary.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_summary.xml
new file mode 100644
index 000000000..b245cb380
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_summary.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry summary xhtml works
+Expect: feed.items.queryElementAt(1, Components.interfaces.nsIFeedEntry).summary.plainText() == "test summary";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:foo="http://www.example.org"
+ foo:quux="quuux"
+ xmlns:content="http://purl.org/rss/1.0/modules/content/">
+
+ <title>hmm</title>
+
+ <author>
+ <email>hmm@example.com</email>
+ <name>foo</name>
+ </author>
+ <generator version="1.1" uri="http://example.org">Hmm</generator>
+ <author>
+ <email>bar@example.com</email>
+ <name>foo</name>
+ </author>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><i>test</i> rights</div>
+ </rights>
+
+
+ <entry></entry>
+
+ <entry foo:bar="baz">
+ <title>test</title>
+ <summary type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml">
+ <b>test</b> summary
+ </div>
+ </summary>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_title.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_title.xml
new file mode 100644
index 000000000..c118e7472
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_title.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom feed and entry with random attributes works
+Expect: feed.items.queryElementAt(1, Components.interfaces.nsIFeedEntry).title.text == "test";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:foo="http://www.example.org"
+ foo:quux="quuux">
+
+ <title>hmm</title>
+
+ <author>
+ <email>hmm@example.com</email>
+ <name>foo</name>
+ </author>
+ <generator version="1.1" uri="http://example.org">Hmm</generator>
+ <author>
+ <email>bar@example.com</email>
+ <name>foo</name>
+ </author>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><i>test</i> rights</div>
+ </rights>
+
+
+ <entry></entry>
+
+ <entry foo:bar="baz">
+ <title>test</title>
+
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_title_normalized.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_title_normalized.xml
new file mode 100644
index 000000000..19e2ac1a6
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_title_normalized.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry title normalized
+Expect: feed.items.queryElementAt(1, Components.interfaces.nsIFeedEntry).title.text == "test";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:foo="http://www.example.org"
+ foo:quux="quuux">
+
+ <title>hmm</title>
+
+ <author>
+ <email>hmm@example.com</email>
+ <name>foo</name>
+ </author>
+ <generator version="1.1" uri="http://example.org">Hmm</generator>
+ <author>
+ <email>bar@example.com</email>
+ <name>foo</name>
+ </author>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><i>test</i> rights</div>
+ </rights>
+
+
+ <entry></entry>
+
+ <entry foo:bar="baz">
+ <title>test</title>
+
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_updated.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_updated.xml
new file mode 100644
index 000000000..4aed7e9c7
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_updated.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom updated works
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).updated == 'Sat, 13 Dec 2003 18:30:02 GMT'
+
+-->
+
+<feed xmlns="http://www.w3.org/2005/Atom">
+
+ <title>Example Feed</title>
+ <link href="http://example.org/"/>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <author>
+ <name>John Doe</name>
+ </author>
+ <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+
+ <entry>
+ <title>Atom-Powered Robots Run Amok</title>
+ <link href="http://example.org/2003/12/13/atom03"/>
+ <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <summary>Some text.</summary>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_w_content_encoded.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_w_content_encoded.xml
new file mode 100644
index 000000000..58f94c6c1
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_w_content_encoded.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry content:encoded and xhtml works
+Expect: var content = feed.items.queryElementAt(1, Components.interfaces.nsIFeedEntry).content.text; content == "<b>test</b> content";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:foo="http://www.example.org"
+ foo:quux="quuux"
+ xmlns:content="http://purl.org/rss/1.0/modules/content/">
+
+ <title>hmm</title>
+
+ <author>
+ <email>hmm@example.com</email>
+ <name>foo</name>
+ </author>
+ <generator version="1.1" uri="http://example.org">Hmm</generator>
+ <author>
+ <email>bar@example.com</email>
+ <name>foo</name>
+ </author>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><i>test</i> rights</div>
+ </rights>
+
+
+ <entry></entry>
+
+ <entry foo:bar="baz">
+ <title>test</title>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml">
+ <b>test</b> content
+ </div>
+ </content>
+ <content:encoded>
+ shouldn't appear
+ </content:encoded>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_xhtml_baseURI_with_amp.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_xhtml_baseURI_with_amp.xml
new file mode 100644
index 000000000..20819cecd
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_xhtml_baseURI_with_amp.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry content xhtml works with a base URI that contains an ampersand.
+Base: http://www.travellerspoint.com/photo_gallery_feed.cfm?tags=Canada&onlyShowFeatured=true
+Expect: var frag = null; var content = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).content; var parser = Components.classes["@mozilla.org/xmlextras/domparser;1"].createInstance(Components.interfaces.nsIDOMParser); var doc = parser.parseFromString("<div/>", "text/xml"); frag = content.createDocumentFragment(doc.documentElement); notEqual(frag, null, "frag is not null"); true;
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:foo="http://www.example.org"
+ foo:quux="quuux">
+
+ <title>hmm</title>
+
+ <author>
+ <email>hmm@example.com</email>
+ <name>foo</name>
+ </author>
+ <generator version="1.1" uri="http://example.org">Hmm</generator>
+ <author>
+ <email>bar@example.com</email>
+ <name>foo</name>
+ </author>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><i>test</i> rights</div>
+ </rights>
+
+ <entry foo:bar="baz">
+ <title>test</title>
+ <content type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml">
+ <b>test</b> content
+ </div>
+ </content>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_xmlBase.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_xmlBase.xml
new file mode 100644
index 000000000..1656e2174
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_xmlBase.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry with xml:base
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link.spec == "http://www.example.org/foo";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <id>tag:example.com,2006:/atom/conformance/linktest/</id>
+ <title>Atom Link Tests</title>
+ <updated>2005-06-18T6:23:00Z</updated>
+ <link href="http://www.example.org" />
+
+ <entry xml:base="http://www.example.org">
+ <id>tag:example.org,2006:/linkreltest/1</id>
+ <title>Does your reader support xml:base properly? </title>
+ <updated>2006-06-23T12:12:12Z</updated>
+ <link href="foo"/>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/entry_xmlBase_on_link.xml b/toolkit/components/feeds/test/xml/rfc4287/entry_xmlBase_on_link.xml
new file mode 100644
index 000000000..0ead14255
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/entry_xmlBase_on_link.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry with xml:base
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link.spec == "http://www.example.org/bar/foo";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+
+ <id>tag:example.com,2006:/atom/conformance/linktest/</id>
+ <title>Atom Link Tests</title>
+ <updated>2005-06-18T16:13:00Z</updated>
+ <link href="http://www.example.org" />
+
+ <entry xml:base="http://www.example.org">
+ <id>tag:example.org,2006:/linkreltest/1</id>
+ <title>Does your reader support xml:base properly? </title>
+ <updated>2006-06-23T12:12:12Z</updated>
+ <link xml:base="/bar/" href="foo"/>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_atom_rights_xhtml.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_atom_rights_xhtml.xml
new file mode 100644
index 000000000..83add3265
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_atom_rights_xhtml.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom rights works with HTML
+Expect: feed.fields.getProperty('atom:rights') != null
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <title type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><b>test</b> title</div>
+ </title>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><i>test</i> rights</div>
+ </rights>
+ <summary type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><div><div>test</div> summary</div></div>
+ </summary>
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_author.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_author.xml
new file mode 100644
index 000000000..790027ee3
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_author.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom author count works
+Expect: feed.authors.length == 1;
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+<title>test title</title>
+<author>
+</author>
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_author2.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_author2.xml
new file mode 100644
index 000000000..eae8292fa
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_author2.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom author count works
+Expect: feed.authors.length == 2
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+<title>test title</title>
+<author>
+</author>
+<author>
+</author>
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_author_email.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_author_email.xml
new file mode 100644
index 000000000..95abdbc8e
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_author_email.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom author name works
+Expect: feed.authors.queryElementAt(0, Components.interfaces.nsIFeedPerson).email=='hmm@example.com';
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+<title>test title</title>
+<author>
+<email>hmm@example.com</email>
+<name>foo</name>
+</author>
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_author_email_2.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_author_email_2.xml
new file mode 100644
index 000000000..71cace773
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_author_email_2.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom author name works
+Expect: feed.authors.queryElementAt(1, Components.interfaces.nsIFeedPerson).email=='bar@example.com';
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+<title>test title</title>
+<author>
+<email>hmm@example.com</email>
+<name>foo</name>
+</author>
+<author>
+<email>bar@example.com</email>
+<name>foo</name>
+</author>
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_author_name.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_author_name.xml
new file mode 100644
index 000000000..2df46f8d5
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_author_name.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom author name works
+Expect: feed.authors.queryElementAt(0, Components.interfaces.nsIFeedPerson).name=='foo';
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+<title>test title</title>
+<author>
+<name>foo</name>
+</author>
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_author_surrounded.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_author_surrounded.xml
new file mode 100644
index 000000000..b15278f91
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_author_surrounded.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom author name works
+Expect: feed.authors.queryElementAt(0, Components.interfaces.nsIFeedPerson).name=='John Doe';
+
+-->
+
+<feed xmlns="http://www.w3.org/2005/Atom">
+
+ <title>Example Feed</title>
+ <link href="http://example.org/"/>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <author>
+ <name>John Doe</name>
+ </author>
+ <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+
+ <entry>
+ <title>Atom-Powered Robots Run Amok</title>
+ <link href="http://example.org/2003/12/13/atom03"/>
+ <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <summary>Some text.</summary>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_author_uri.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_author_uri.xml
new file mode 100644
index 000000000..44149036c
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_author_uri.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom author uri works
+Expect: feed.authors.queryElementAt(1, Components.interfaces.nsIFeedPerson).uri.spec =='http://example.com/';
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+<title>test title</title>
+<author>
+<email>hmm@example.com</email>
+<name>foo</name>
+<uri>http://example.org</uri>
+</author>
+<author>
+<email>bar@example.com</email>
+<name>foo</name>
+<uri>http://example.com/</uri>
+</author>
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_comment_rss_extra_att.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_comment_rss_extra_att.xml
new file mode 100644
index 000000000..795d3f6ad
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_comment_rss_extra_att.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: wfw works with extra attribute
+Expect: feed.fields.getProperty('wfw:commentRss') == 'http://example.org'
+
+-->
+
+<feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:foo="http://example.org"
+ xmlns:bla="http://wellformedweb.org/CommentAPI/">
+
+ <title>Example Feed</title>
+ <link href="http://example.org/"/>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <author>
+ <name>John Doe</name>
+ </author>
+ <id foo:bar="baz">urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+ <bla:commentRss hmm="yeah">http://example.org</bla:commentRss>
+ <entry>
+ <title>Atom-Powered Robots Run Amok</title>
+ <link href="http://example.org/2003/12/13/atom03"/>
+ <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <summary>Some text.</summary>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_contributor.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_contributor.xml
new file mode 100644
index 000000000..abb50c154
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_contributor.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom contributor uri works
+Expect: feed.contributors.queryElementAt(1, Components.interfaces.nsIFeedPerson).uri.spec=='http://example.com/';
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <title>test title</title>
+ <contributor>
+ <email>hmm@example.com</email>
+ <name>foo</name>
+ <uri>http://example.org</uri>
+ </contributor>
+ <contributor>
+ <email>bar@example.com</email>
+ <name>foo</name>
+ <uri>http://example.com</uri>
+ </contributor>
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_entry_count.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_entry_count.xml
new file mode 100644
index 000000000..53028d3d1
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_entry_count.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom entry count works
+Expect: feed.items.length == 3
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <title>test title</title>
+ <logo>http://example.org/logo.jpg</logo>
+ <entry></entry>
+ <entry></entry>
+ <entry></entry>
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_generator.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_generator.xml
new file mode 100644
index 000000000..5112775b9
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_generator.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom generator works
+Expect: feed.generator.agent == 'Hmm';
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+
+<author>
+<email>hmm@example.com</email>
+<name>foo</name>
+</author>
+
+
+ <generator>Hmm</generator>
+
+<author>
+<email>bar@example.com</email>
+<name>foo</name>
+</author>
+
+
+ <title type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><b>test</b> title</div>
+ </title>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><i>test</i> rights</div>
+ </rights>
+ <summary type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><div><div>test</div> summary</div></div>
+ </summary>
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_generator_uri.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_generator_uri.xml
new file mode 100644
index 000000000..a4b8c735c
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_generator_uri.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom generator works
+Expect: feed.generator.uri.spec == 'http://example.org/';
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+
+<author>
+<email>hmm@example.com</email>
+<name>foo</name>
+</author>
+
+
+ <generator uri="http://example.org">Hmm</generator>
+
+<author>
+<email>bar@example.com</email>
+<name>foo</name>
+</author>
+
+
+ <title type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><b>test</b> title</div>
+ </title>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><i>test</i> rights</div>
+ </rights>
+ <summary type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><div><div>test</div> summary</div></div>
+ </summary>
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_generator_uri_xmlbase.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_generator_uri_xmlbase.xml
new file mode 100644
index 000000000..54191b50e
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_generator_uri_xmlbase.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom generator works
+Expect: feed.generator.uri.spec == 'http://example.org/gen/';
+
+-->
+<feed xml:base="http://example.org/" xmlns="http://www.w3.org/2005/Atom">
+
+<author>
+<email>hmm@example.com</email>
+<name>foo</name>
+</author>
+
+
+ <generator uri="/gen/">Hmm</generator>
+
+<author>
+<email>bar@example.com</email>
+<name>foo</name>
+</author>
+
+
+ <title type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><b>test</b> title</div>
+ </title>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><i>test</i> rights</div>
+ </rights>
+ <summary type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><div><div>test</div> summary</div></div>
+ </summary>
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_generator_version.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_generator_version.xml
new file mode 100644
index 000000000..845ce7504
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_generator_version.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom generator works
+Expect: feed.generator.version == "1.1"
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+
+<author>
+<email>hmm@example.com</email>
+<name>foo</name>
+</author>
+
+
+ <generator version="1.1" uri="http://example.org">Hmm</generator>
+
+<author>
+<email>bar@example.com</email>
+<name>foo</name>
+</author>
+
+
+ <title type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><b>test</b> title</div>
+ </title>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><i>test</i> rights</div>
+ </rights>
+ <summary type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><div><div>test</div> summary</div></div>
+ </summary>
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_icon.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_icon.xml
new file mode 100644
index 000000000..017aafbad
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_icon.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom icon works
+Expect: feed.fields.getProperty('atom:icon') == 'http://example.org/favicon.ico'
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <title>test title</title>
+ <icon>http://example.org/favicon.ico</icon>
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_id.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_id.xml
new file mode 100644
index 000000000..6c538e801
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_id.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom author name works
+Expect: feed.fields.getProperty('atom:id') == 'urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6' && feed.id == 'urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6'
+
+-->
+
+<feed xmlns="http://www.w3.org/2005/Atom">
+
+ <title>Example Feed</title>
+ <link href="http://example.org/"/>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <author>
+ <name>John Doe</name>
+ </author>
+ <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+
+ <entry>
+ <title>Atom-Powered Robots Run Amok</title>
+ <link href="http://example.org/2003/12/13/atom03"/>
+ <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <summary>Some text.</summary>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_id_extra_att.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_id_extra_att.xml
new file mode 100644
index 000000000..ef718463b
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_id_extra_att.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom feed id works with extra attribute
+Expect: feed.fields.getProperty('atom:id') == 'urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6'
+
+-->
+
+<feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:foo="http://example.org">
+
+ <title>Example Feed</title>
+ <link href="http://example.org/"/>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <author>
+ <name>John Doe</name>
+ </author>
+ <id foo:bar="baz">urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+
+ <entry>
+ <title>Atom-Powered Robots Run Amok</title>
+ <link href="http://example.org/2003/12/13/atom03"/>
+ <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <summary>Some text.</summary>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_logo.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_logo.xml
new file mode 100644
index 000000000..2a90fe22b
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_logo.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom logo works
+Expect: feed.image.getProperty('url') == 'http://example.org/logo.jpg'
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <title>test title</title>
+ <logo xml:base="http://example.org/">logo.jpg</logo>
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_random_attributes_on_feed_and_entry.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_random_attributes_on_feed_and_entry.xml
new file mode 100644
index 000000000..a4c5633e2
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_random_attributes_on_feed_and_entry.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom feed and entry with random attributes works
+Expect: feed.title.text == "hmm" && feed.items.length == 2
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom"
+ xmlns:foo="http://www.example.org"
+ foo:quux="quuux">
+
+ <title>hmm</title>
+
+ <author>
+ <email>hmm@example.com</email>
+ <name>foo</name>
+ </author>
+ <generator version="1.1" uri="http://example.org">Hmm</generator>
+ <author>
+ <email>bar@example.com</email>
+ <name>foo</name>
+ </author>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><i>test</i> rights</div>
+ </rights>
+
+ <entry foo:bar="baz"></entry>
+ <entry></entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_rights_normalized.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_rights_normalized.xml
new file mode 100644
index 000000000..b7ef46047
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_rights_normalized.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom rights works normalized
+Expect: feed.rights.plainText() == "test rights"
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <title type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><b>test</b> title</div>
+ </title>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><b>test</b> rights</div>
+ </rights>
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_rights_xhtml.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_rights_xhtml.xml
new file mode 100644
index 000000000..422c6fb49
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_rights_xhtml.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom rights works
+Expect: feed.fields.getProperty('atom:rights') != null
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <title type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><b>test</b> title</div>
+ </title>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><b>test</b> rights</div>
+ </rights>
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_rights_xhtml_nested_divs.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_rights_xhtml_nested_divs.xml
new file mode 100644
index 000000000..ebad24ac3
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_rights_xhtml_nested_divs.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom rights works with nested divs
+Expect: feed.fields.getProperty('atom:rights') != null
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <title type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><b>test</b> title</div>
+ </title>
+ <rights type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><div><div>test</div> rights</div></div>
+ </rights>
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_subtitle.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_subtitle.xml
new file mode 100644
index 000000000..096061399
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_subtitle.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom subtitle works
+Expect: var sub = feed.subtitle.text; sub == '<b>test</b> subtitle';
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <subtitle type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><b>test</b> subtitle</div>
+ </subtitle>
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_tantek_title.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_tantek_title.xml
new file mode 100644
index 000000000..cba9a4918
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_tantek_title.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Description: XHTML title with apos
+Expect: feed.title.plainText() == "Tantek's Updates"
+-->
+<feed xml:lang="en-US"
+ xmlns="http://www.w3.org/2005/Atom">
+ <title type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml">Tantek's Updates</div>
+ </title>
+ <link href="http://tantek.com/"
+ rel="alternate" title="Tantek's Posts" type="text/html"/>
+ <link href="http://tantek.com/updates.atom"
+ rel="self" />
+ <id>http://tantek.com/updates.atom</id>
+ <author>
+ <name>Tantek</name>
+ <uri>http://tantek.com/</uri>
+ </author>
+ <updated>2006-05-02T20:13:00-07:00</updated>
+ <entry>
+ <updated>2006-04-22T00:00:00-07:00</updated>
+ <published>2006-04-22T00:00:00-07:00</published>
+ <link href="http://www.makezine.com/faire/"
+ rel="alternate" title="Make Faire" type="text/html"/>
+ <id>http://www.makezine.com/faire/</id>
+ <title>Make Faire</title>
+ <content type="xhtml" xml:space="preserve">
+ <div xmlns="http://www.w3.org/1999/xhtml">
+ <div class="vevent">
+ <a class="url" href="http://www.makezine.com/faire/">
+ <abbr class="dtstart" title="20060422">
+ 4/22</abbr>-<abbr class="dtend" title="20060424">23</abbr>
+
+ <span class="summary">
+ Make Faire
+ </span> @
+ <span class="location">
+ San Mateo Fairgrounds
+ </span>
+ </a>
+ </div>
+ </div>
+ </content>
+ </entry>
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_title.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_title.xml
new file mode 100644
index 000000000..6e0cea003
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_title.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom title works
+Expect: feed.title.text == 'test title'
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+<title>test title</title>
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_title_full_feed.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_title_full_feed.xml
new file mode 100644
index 000000000..cef3f84a3
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_title_full_feed.xml
@@ -0,0 +1,936 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+Description: Feed title works with full entry
+Expect: feed.title.text == 'ongoing'
+-->
+<feed xmlns='http://www.w3.org/2005/Atom'
+ xml:base='http://www.tbray.org/ongoing/ongoing.atom'
+ xml:lang='en-us'>
+ <title>ongoing</title>
+ <id>http://www.tbray.org/ongoing/</id>
+ <link href='./' />
+ <link rel='self' href='' />
+ <logo>rsslogo.jpg</logo>
+ <icon>/favicon.ico</icon>
+ <updated>2006-04-26T20:10:25-08:00</updated>
+ <author><name>Tim Bray</name></author>
+ <subtitle>ongoing fragmented essay by Tim Bray</subtitle>
+ <rights>All content written by Tim Bray and photos by Tim Bray Copyright Tim Bray, some rights reserved, see /ongoing/misc/Copyright</rights>
+ <generator uri='/misc/Colophon'>Generated from XML source code using Perl, Expat, XML::Parser, Emacs, Mysql, and ImageMagick. Industrial strength technology, baby.</generator>
+
+<entry xml:base='When/200x/2006/04/26/'>
+ <title>Spring in White on White</title>
+ <link href='Spring-in-White-on-White' />
+ <id>http://www.tbray.org/ongoing/When/200x/2006/04/26/Spring-in-White-on-White</id>
+ <published>2006-04-26T13:00:00-08:00</published>
+ <updated>2006-04-26T20:10:16-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Arts/Photos' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Arts' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Photos' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Garden' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Garden' />
+ <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>Most people would generally prefer a climate where it&#x2019;s bright and warm most of the time. But for Canadians and others who live where it&#x2019;s not, there are compensations, and one is the experience of spring. I have a picture.</div></summary>
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p>Most people would generally prefer a climate where it’s bright
+and warm most of the time. But for Canadians and others who live where it’s
+not, there are compensations, and one is the experience of
+spring. I have a picture.</p>
+<img src="IMGP3247.png" alt="Pear blossoms against cherry blossoms" />
+<div class="caption"><p>The blossoms are pear in the foreground, cherry behind.</p></div>
+<p>After all the months of 50° North Latitude winter—icy-sharp in most
+of Canada, wet and dark here in Vancouver—the soul, the spirit, and the
+libido all spring to life when the sun comes back. We’ve had a solid year of
+crappy weather, but this last Saturday through Monday were solidly summery,
+bright
+and warm; and in this season the days are already long and each gets
+longer so fast you can feel it.</p>
+<p>On the back porch, our pear tree’s branches were silhouetted against the
+neighbors’ big wild old cherry; the cherry yields no edible fruit but who
+cares, it’s beautiful
+tree any time of year.</p>
+</div></content></entry>
+
+<entry xml:base='When/200x/2006/04/26/'>
+ <title>Scott</title>
+ <link href='Scott' />
+ <id>http://www.tbray.org/ongoing/When/200x/2006/04/26/Scott</id>
+ <published>2006-04-26T13:00:00-08:00</published>
+ <updated>2006-04-26T20:06:50-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Business/Sun' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Business' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Sun' />
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p>I’ve been watching our internal leadership conference and spending quite a
+bit of time talking in the virtual hallways, and I’ve been surprised at
+the intensity of feeling about Mr. McNealy. Yes, there are those
+here saying “About bloody time, now we can make some progress” but there’s a
+much bigger group that is genuinely emotional about this transition.
+Maybe it’s a function of seniority: I never met nor corresponded with Scott, and
+he hasn’t been
+much of a presence in the company’s conversation in the time I’ve been here.
+But there are a lot of smart, seasoned, unsentimental people making it clear
+that
+he’s been a major force in their lives, at a more personal level than I’m
+used to hearing when people speak about executives. I guess also that to a
+lot of people, Sun’s vision, for which Scott gets some of the credit, was a
+radical and wonderful thing. I first used Unix in 1979 and quit a nice
+big-company job
+to become a VAX-bsd sysadmin in 1983, so I’ve always kind of
+lived inside that vision.
+But I’ll tell you one thing, what I’ve been hearing the last couple of days
+makes me really regret that I didn’t get to know Scott.</p>
+</div></content></entry>
+
+<entry xml:base='When/200x/2006/04/26/'>
+ <title>Jacobs, Pictures, Spartans</title>
+ <link href='Jane-Jacobs' />
+ <id>http://www.tbray.org/ongoing/When/200x/2006/04/26/Jane-Jacobs</id>
+ <published>2006-04-26T13:00:00-08:00</published>
+ <updated>2006-04-26T17:28:59-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='The World' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='The World' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Arts/Photos' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Arts' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Photos' />
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p><a href="http://en.wikipedia.org/wiki/Jane_Jacobs">Jane Jacobs</a> died;
+the city I live in, Vancouver, is pretty solidly Jacobsian both in its current
+shape and its planning dogma. By choosing to live here I’m empirically a
+fan. Oddly, few have remarked how great Jacobs
+<em>looked</em>; her face commanded the eye. Which leads me Alex
+Waterhouse-Hayward’s wonderful
+<a href="http://www.alexwaterhousehayward.com/blog/2006/04/jane-jacobs-viveca-lindfors_26.html">Jane Jacobs &amp; Viveca Lindfors</a>;
+surprising portraits and thoughts on decoration. W-H’s blog has become one of
+only two or three that I
+stab at excitedly whenever I see something new. For example, see
+<a href="http://www.alexwaterhousehayward.com/blog/archives/2006_04_01_archive.html#114476408248660848">Sex Crimes, Homicide and Drugs</a>
+and yes, that’s what it’s about.
+Staying with the death-and-betrayal theme, and apparently (but not really)
+shifting back 2&#xbd; millennia, see John Cowan’s
+<a href="http://recycledknowledge.blogspot.com/2006/04/war-after-simonides.html">The
+War (after Simonides)</a>, being careful to look closely at the links.
+I’ve
+<a href="http://www.tbray.org/ongoing/When/200x/2003/03/24/Herodotus">written</a>
+about those same wars.</p>
+</div></content></entry>
+
+<entry xml:base='When/200x/2006/04/25/'>
+ <title>LAMP and MARS</title>
+ <link href='Scaling-Rails' />
+ <id>http://www.tbray.org/ongoing/When/200x/2006/04/25/Scaling-Rails</id>
+ <published>2006-04-25T13:00:00-08:00</published>
+ <updated>2006-04-26T07:24:06-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology/Web' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Web' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology/Sun' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Sun' />
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p>At
+<a href="/ongoing/When/200x/2006/04/13/RoR">that Rails conference</a>, when I
+was
+<a href="http://blog.garbledygook.com/2006/04/17/ruby-on-rails-podcast-tim-bray-ruby-on-rails-podcast/">talking</a>
+to
+<a href="http://jroller.com/page/obie">Obie Fernandez</a>, he asked, more or
+less “How can Sun love us? We’re not Java” and I said, more or less, “Hey,
+you’re programmers, you write software and there have to be computers to run
+it, we sell computers, why wouldn’t we love you?” Anyhow, we touched on
+parallelism a bit and I talked up the
+<a href="http://www.sun.com/processors/UltraSPARC-T1/">T1</a>;
+Obie took that ball and
+<a href="http://jroller.com/page/obie?entry=will_ultrasparc_t1_emerge_as">ran with it</a>,
+saying all sorts of positive things about synergy between Rails’
+shared-nothing architecture and our multicore systems. Yeah, well, good in
+theory, but I’m too old to make that kind of prediction without running some
+tests. Hah, it turns out that
+<a href="http://joyent.com/">Joyent</a> has been
+<a href="http://scalewithrails.com/">doing that</a>, and have
+<a href="http://scalewithrails.com/downloads/ScaleWithRails-April2006.pdf">76
+PDF slides</a> on the subject.
+If you care about big-system scaling issues, read the whole thing; a little
+long, but amusing and with hardly any bullet lists. If you’re a Sun
+shareholder looking for a pick-me up, check out slides 40-41, 49, and 52-74.
+Oh, I gather that the T1, Solaris, and ZFS are OK for Java too.
+<i>[Update: The title was just “SAMR”, as in LAMP with two new letters.
+Enough people didn’t get it that I was forced to think about it, and MARS
+works better anyhow.]</i></p>
+</div></content></entry>
+
+<entry xml:base='When/200x/2006/04/25/'>
+ <title>Real-Time Journalism</title>
+ <link href='Talk-With-Berlind' />
+ <id>http://www.tbray.org/ongoing/When/200x/2006/04/25/Talk-With-Berlind</id>
+ <published>2006-04-25T13:00:00-08:00</published>
+ <updated>2006-04-26T06:40:19-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='The World/Journalism' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='The World' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Journalism' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology/Syndication' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Syndication' />
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p>I got email late yesterday from
+<a href="http://blogs.zdnet.com/bio.php#berlind">David Berlind</a>: “Hey, can
+I call you for a minute?” He wanted commentary on
+<a href="http://blogs.zdnet.com/BTL/?p=2906">a story he was writing</a> that I
+think is about the potential for intellectual-property lock-ins on RSS and Atom
+extensions. I say “I think is about” because the headline is “Will or could
+RSS get forked?”. After a few minutes’ chat, David asked if he could record
+for a podcast, and even though I only had a cellphone, the audio came out OK.
+The conversation was rhythmic: David brought up a succession of potential
+issues and answered each along the lines of “Yes, it’s reasonable to worry
+about that, but in this
+case I don’t see any particular problems.”
+Plus I emitted a mercifully-brief rant on the difference between protocols,
+data, and software.
+On the one hand, I thought David could have been a
+little clearer that I was pushing back against the thrust of his story, but on
+the other hand he included the whole conversation right
+there in the piece, so anyone who actually cares can listen and find out what
+I actually said, not what I think I said nor what David reported I said.
+I find this raw barely-intermediated journalism (we
+talk on the phone this afternoon, it’s on the Web in hours) a little
+shocking still.
+On balance, it’s better than the way we used to do things.</p>
+</div></content></entry>
+
+<entry xml:base='When/200x/2006/04/24/'>
+ <title>The Transition Explained</title>
+ <link href='CEO-Transition' />
+ <id>http://www.tbray.org/ongoing/When/200x/2006/04/24/CEO-Transition</id>
+ <published>2006-04-24T13:00:00-08:00</published>
+ <updated>2006-04-24T16:49:05-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Business/Sun' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Business' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Sun' />
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p>It’s not that complicated, really.
+Bloggers are
+<a href="http://www.sun.com/2006-0418/js/index.jsp">taking over the world</a>.
+Resistance is futile; you will be assimilated.</p>
+</div></content></entry>
+
+<entry xml:base='When/200x/2006/04/24/'>
+ <title>5&#x272d;&#x266b;: One More Cup of Coffee</title>
+ <link href='One-More-Cup-Of-Coffee' />
+ <id>http://www.tbray.org/ongoing/When/200x/2006/04/24/One-More-Cup-Of-Coffee</id>
+ <published>2006-04-24T13:00:00-08:00</published>
+ <updated>2006-04-24T13:00:00-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Arts/Music/Recordings' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Arts' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Music' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Recordings' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Arts/Music/5 Stars' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='5 Stars' />
+ <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>I&#x2019;m not really a <a href='http://en.wikipedia.org/wiki/Bob_Dylan'>Bob Dylan</a> fan. A voice like that, and a tunesmithing talent like that, come along only a few times per century, but he&#x2019;s still kind of irritating. That aside, the song <cite>One More Cup of Coffee</cite>, from the 1976 album <a href='http://en.wikipedia.org/wiki/Desire_%28album%29'>Desire</a>, can&#x2019;t be ignored; wonderful tune, wonderful orchestration, wonderful performance. <i>(&#x201c;5&#x272d;&#x266b;&#x201d; series introduction <a href='/ongoing/When/200x/2006/01/23/5-Star-Music'>here</a>; with <a href='/ongoing/When/200x/2006/01/23/5-Star-Music#p-1'>an explanation</a> of why the title may look broken.)</i></div></summary>
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p>I’m not really a
+<a href="http://en.wikipedia.org/wiki/Bob_Dylan">Bob Dylan</a> fan. A voice
+like that, and a tunesmithing talent like that, come along only a few times
+per century, but he’s still kind of irritating.
+That aside, the song <cite>One More Cup of Coffee</cite>, from the 1976 album
+<a href="http://en.wikipedia.org/wiki/Desire_%28album%29">Desire</a>, can’t be
+ignored; wonderful tune, wonderful orchestration, wonderful performance.
+<i>(“5✭♫” series introduction <a href="/ongoing/When/200x/2006/01/23/5-Star-Music">here</a>;
+with <a href="/ongoing/When/200x/2006/01/23/5-Star-Music#p-1">an
+explanation</a> of why the title may look broken.)</i></p>
+<img src="Desire.png" class="inline" alt="Desire, by Bob Dylan" />
+<h2 id='p-1'>The Context</h2>
+<p>Nothing I can possibly write will add any wisdom to the
+millions of words, some 90% of them in excess of needs, written on the subject
+of this particular person.</p>
+<p>A personal statement: Bob Dylan has long irritated me for, during the first
+thirty years or
+so of his career, never having given a straight answer to a straight question,
+and for writing songs with dozens of boring verses. But they’ll still be
+listening
+to lots of his performances long after I’m dead, and in recent years he’s
+become a better, more direct, interview.</p>
+<p>My taste in Dylan is a little unusual: once you get past <cite>One More Cup
+of Coffee</cite>, my favorites would be <cite>Baby Let Me Follow You
+Down</cite> (from the <cite>Last Waltz</cite> soundtrack) and
+<cite>Crash on the Levee (Down in the Flood)</cite> from
+<a href="http://en.wikipedia.org/wiki/The_Basement_Tapes">The Basement
+Tapes</a>.</p>
+<p><cite>Desire</cite>, the record, is hit and miss. <cite>Joey</cite>,
+glorification of the life of some mafioso, is flawed in concept
+and unlistenable in execution. <cite>Hurricane</cite>, whatever you think
+about
+<a href="http://en.wikipedia.org/wiki/Rubin_Carter">Mr. Carter</a>, that song
+rocks; and <cite>Isis</cite> hits pretty hard too.</p>
+<h2 id='p-2'>The Music</h2>
+<p>Is there anything in <cite>One More Cup of Coffee</cite> that’s not
+perfect? Well yes, in the verses, the
+lyrics on occasion drag (“He oversees his kingdom / So no stranger does
+intrude / His voice it trembles as he calls out / For another plate of food”).
+But apart from that, the sentiment is compelling,
+<a href="http://en.wikipedia.org/wiki/Scarlet_Rivera">Scarlet Rivera’s</a>
+violin is beautifully scored and played, the tune is to die for, and the
+backing vocals are by Emmylou Harris, who you can bet is going to be here in
+the 5-✭ series one of these days.
+And while there’s not much middle ground on the subject of Dylan’s singing, if
+you like it, you’ll <em>really</em> like this song.</p>
+<p>Listen to the choruses: Bob and Emmylou veer wildly around the rhythm, then
+coalesce on the beat when it matters, and they’re making it
+up as they go along, they’re wholly inhabiting the moment, and it’s
+quite, quite perfect.</p>
+<h2 id='p-3'>Sampling It</h2>
+<p>Oh yeah, it’s out there. And there’s a live version too; but the smart
+thing would be to go buy the un-compressed un-DRM’ed shiny round silver
+version of <cite>Desire</cite>; it’s a keeper.</p>
+</div></content></entry>
+
+<entry xml:base='When/200x/2006/04/24/'>
+ <title>Atomic Monday</title>
+ <link href='Atomic-Monday' />
+ <id>http://www.tbray.org/ongoing/When/200x/2006/04/24/Atomic-Monday</id>
+ <published>2006-04-24T13:00:00-08:00</published>
+ <updated>2006-04-24T00:44:06-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology/Syndication' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Syndication' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology/Atom' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Atom' />
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p>First of all, implementors of anything Atom-related need to spend some time
+<a href="http://golem.ph.utexas.edu/~distler/blog/archives/000793.html">chez
+Jacques Distler</a>; in particular, the conversation that plays out in the
+comments. Second, there’s this piece of software called
+<a href="http://www.planetplanet.org/">Planet Planet</a> that allows you to
+make an aggregate web page by reading lots of feeds; for example, see
+<a href="http://www.planetapache.org/">Planet Apache</a> or
+<a href="http://planetsun.org/">Planet Sun</a>.
+Sam Ruby decided that its Atom support needed some work, so
+<a href="http://www.intertwingly.net/blog/2006/04/23/Adding-Atom-support-to-PlanetPlanet">he did
+it</a>. Now, here’s the exciting part: he pinged me over the weekend and said
+“Hey, look at this” wanting to show me his cleverly-Atomized
+Planet Intertwingly feed.
+I looked at it in
+<a href="http://ranchero.com/netnewswire/">NetNewsWire</a> and was puzzled for
+a moment; some but not all of the
+things in the feed were highlighted as unread, even though this was the first
+time I’d seen it. Then the light went on.
+This
+is Atom doing <em>exactly what we went to all that trouble to make it do</em>.
+NetNewsWire has good Atom support and, because Atom entries all have unique
+IDs and timestamps, it can
+tell that it’s seen lots of those entries before in other feeds that I
+subscribe to. That’s how I found Jacques’ piece. This is huge; anyone who
+uses synthetic or aggregated feeds knows that dupes are a big problem, showing
+up all over the place.
+No longer, Atom makes that problem go away.</p>
+</div></content></entry>
+
+<entry xml:base='When/200x/2006/04/22/'>
+ <title>Hyatt on the High-Res Web</title>
+ <link href='High-Res-Web' />
+ <id>http://www.tbray.org/ongoing/When/200x/2006/04/22/High-Res-Web</id>
+ <published>2006-04-22T13:00:00-08:00</published>
+ <updated>2006-04-23T17:12:18-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology/Web' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Web' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology/Presentation' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Presentation' />
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p>Check out Dave Hyatt’s
+<a href="http://webkit.opendarwin.org/blog/?p=55">excellent write-up</a> on
+designing and rendering Web pages so they take advantage of the
+higher-resolution screens that <em>may</em> be coming our way.
+I emphasize “may” because I’ve seen how slowly we’ve picked up pixels over
+the years. The first really substantial screen I ever worked on was a
+1988-vintage Sun workstation with about a million pixels. The Mac on my
+lap right now, which has 125 times as much memory as that workstation, has
+only 1.38 million pixels.
+Anyhow, Hyatt has some smart things to say on the issues,
+which are trickier than you might think. I suspect that sometime in a couple of
+years, if I still care about <span class='o'>ongoing</span>, I’m going to
+have to go back and reprocess all the images so that higher-res versions are
+available for those who have the screens and don’t mind downloading bigger
+files.
+Anyhow, Dave’s piece may be slightly misleading in that he talks about SVG
+as though
+it’s something coming in the future. Not so, check out
+<a href="http://zcorpan.1go.dk/sandbox/svg/atom/.xml">this nifty SVG Atom
+logo</a>, which works fine in all the Mozilla browsers I have here.
+Load it up, resize the window, and watch what happens. Then do a “view
+source”.
+<i>[Update:
+<a href="http://blog.codedread.com">Jeff Schiller</a> writes to tell me that
+Opera 9 does SVG (and Opera 8 “SVG Tiny”) too.]
+[<a href="http://www.freeke.org/ffg">Dave Walker</a> writes: Though the shipping version of Safari doesn’t support SVG,
+<a href="http://nightly.webkit.org/builds/Latest-WebKit-SVN.dmg">the
+nightlies</a> do.]
+[<a href="http://www.davelemen.com/archives/2006/04/is_it_time_for_jpeg_2000_to_go_mainstream.html">Dave Lemen</a>
+points to
+<a href="http://en.wikipedia.org/wiki/JPEG-2000">JPEG 2000</a> as possibly
+useful in a high-res context.]</i></p>
+</div></content></entry>
+
+<entry xml:base='When/200x/2006/04/23/'>
+ <title>Wrong About the Infield Fly Rule</title>
+ <link href='Wrong-About-the-Infield-Fly-Rule' />
+ <id>http://www.tbray.org/ongoing/When/200x/2006/04/23/Wrong-About-the-Infield-Fly-Rule</id>
+ <published>2006-04-23T13:00:00-08:00</published>
+ <updated>2006-04-23T15:02:41-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='The World/Family' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='The World' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Family' />
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p>My brother
+<a href="http://takingalongview.blogspot.com/">Rob</a> is really taking to
+this blogging medium. Check out his recent
+<a href="http://takingalongview.blogspot.com/2006/04/credo.html">Credo</a>,
+and also the only instance I’ve seen of
+<a href="http://takingalongview.blogspot.com/2006/04/ode-to-96-chevy-lumina.html">Anglo-Saxon alliterative poetry</a>
+applied to a mini-van.</p>
+</div></content></entry>
+
+<entry xml:base='When/200x/2004/12/12/'>
+ <title>Statistics</title>
+ <link href='BMS' />
+ <id>http://www.tbray.org/ongoing/When/200x/2004/12/12/BMS</id>
+ <published>2004-12-12T12:00:00-08:00</published>
+ <updated>2006-04-23T10:10:02-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology/Publishing' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Publishing' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology/Web' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Web' />
+ <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>Almost every Sunday I grab the week&#x2019;s <span class="o">ongoing</span> logfiles and update my numbers. I find it interesting and maybe others will too, so this entry is now the charts&#x2019; permanent home. I&#x2019;ll update it most weeks, probably. <i>[Updated: 2006/04/23.]</i></div></summary>
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p>Almost every Sunday I grab the week’s <span class='o'>ongoing</span>
+logfiles and update my numbers.
+I find it interesting
+and maybe others will too, so
+this entry is now the charts’ permanent home. I’ll update it most weeks,
+probably.
+<i>[Updated: 2006/04/23.]</i></p>
+<img src="Browser-Market-Share.png" alt="Browser market shares at ‘ongoing’" />
+<div class="caption"><p>Browsers visiting <span class='o'>ongoing</span>,
+percent.</p></div>
+<img src="Browsers-via-search.png" alt="Browser market shares at ‘ongoing’, visitors via search engines" />
+<div class="caption"><p>Browsers visiting <span class='o'>ongoing</span> via
+search engines, percent.</p></div>
+<img src="Search-Engines.png" alt="Search engine market shares at ‘ongoing’" />
+<div class="caption"><p>Search referrals to <span
+class='o'>ongoing</span> .</p></div>
+<img src="Feeds.png" alt="RSS and Atom feed fetches" />
+<div class="caption"><p>Fetches of the RSS 2.0 and Atom 1.0 feeds.</p></div>
+<p>The notes on usage and source code will return in coming weeks when I get
+the cycles to rewrite this whole article.</p>
+<h2 id='p-1'>What a “Hit” Means</h2>
+<p>I recently
+<a href="/ongoing/When/200x/2006/02/07/Thumbnail">updated</a> the
+<a href="/ongoing/misc/Colophon"><span class='o'>ongoing</span> software</a>
+(but haven’t updated the Colophon I see, oops).
+Anyhow, the <code>XMLHttpRequest</code> now issued by each page seems to be a
+pretty reliable counter of the number of actual browsers with humans behind
+them reading the pages. I checked against
+<a href="/ongoing/When/200x/2005/12/04/Google-Analytics">Google Analytics</a>
+and the numbers agreed to within a dozen or two on days with 5,000 to 10,000
+page views; interestingly, Google Analytics was always 10 or 20 views
+higher.</p>
+<p>Anyhow, do <em>not</em> conclude that now I know how many people are
+reading whatever it is I write here; because I publish lots of short pieces
+that are all there in my RSS feed, and anyone reading my Atom feed gets the
+full content of everything.
+I and I have <em>no #&amp;*!$ idea</em> how many people look at my feeds.</p>
+<p>By the way, this was the first time in weeks and weeks that I’d looked at the
+Analytics numbers, and they showed almost exactly zero change from the report
+linked above. So I’m going to turn them off; they’re a little too intrusive
+and I think may be slowing page loads.</p>
+<p>Anyhow, I ran some detailed statistics on the traffic for Wednesday,
+February 8th, 2006.</p>
+<table cellspacing="3" cellpadding="2" class="wltable">
+<tr valign="top"><td>Total connections to the server</td><td align="right">180,428</td></tr>
+<tr valign="top"><td>Total successful GET transactions</td><td align="right">155,507</td></tr>
+<tr valign="top"><td>Total fetches of the RSS and Atom feeds</td><td align="right">88,450</td></tr>
+<tr valign="top"><td>Total GET transactions that actually fetched data (i.e. status code
+200 as opposed to 304)</td><td align="right">87,271</td></tr>
+<tr valign="top"><td>Total GETs of actual ongoing pages (i.e. not CSS, js, or
+images)</td><td align="right">18,444</td></tr>
+<tr valign="top"><td>Actual human page-views</td><td align="right">6,348</td>
+</tr>
+</table>
+<p>So, there you have it. Doing a bit of rounding, if you take the 180K
+transactions and subtract the 90K feed fetches and the 6000 actual human page
+views, you’re left with 84,000 or so “Web overhead” transactions, mostly
+stylesheets and graphics and so on.
+For every human who viewed a page, it was fetched almost twice again by
+various kinds of robots and non-browser automated agents.</p>
+<p>It’s amazing that the whole thing works at all.</p>
+</div></content></entry>
+
+<entry xml:base='When/200x/2006/04/18/'>
+ <title>XML Automaton</title>
+ <link href='XML-Grammar' />
+ <id>http://www.tbray.org/ongoing/When/200x/2006/04/18/XML-Grammar</id>
+ <published>2006-04-18T13:00:00-08:00</published>
+ <updated>2006-04-23T08:25:56-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology/XML' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='XML' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology/Coding' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Coding' />
+ <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>In December of 1996 I released a piece of software called <a href='http://www.textuality.com/Lark/'>Lark</a>, which was the world&#x2019;s first <a href='http://www.w3.org/TR/REC-xml/#dt-xml-proc'>XML Processor</a> (as the term is defined in the <a href='http://www.w3.org/TR/REC-xml/'>XML Specification</a>). It was successful, but I stopped maintaining it in 1998 because lots of other smart people, and some big companies like Microsoft, were shipping perfectly good processors. I never <em>quite</em> open-sourced it, holding back one clever bit in the moronic idea that I could make money out of Lark somehow. The magic sauce is a finite state machine that can be used to parse XML 1.0. Recently, someone out there needed one of those, so I thought I&#x2019;d publish it, with some commentary on Lark&#x2019;s construction and an amusing anecdote about the name. I doubt there are more than twelve people on the planet who care about this kind of parsing arcana. <i>[Rick Jelliffe <a href='http://www.oreillynet.com/xml/blog/2006/04/xml_in_xml.html'>has upgraded</a> the machine].</i></div></summary>
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p>In December of 1996 I released a piece of software called
+<a href="http://www.textuality.com/Lark/">Lark</a>, which was
+the world’s first
+<a href="http://www.w3.org/TR/REC-xml/#dt-xml-proc">XML Processor</a> (as the
+term is defined in the
+<a href="http://www.w3.org/TR/REC-xml/">XML Specification</a>).
+It was successful, but I stopped maintaining it in 1998 because lots of other
+smart people, and some big companies like Microsoft, were shipping perfectly
+good processors. I never <em>quite</em> open-sourced it, holding back one
+clever bit in the moronic idea that I could make money out of Lark somehow.
+The magic sauce is a finite state machine that can be used to parse XML 1.0.
+Recently, someone out there needed one of those, so I thought I’d publish
+it, with some commentary on Lark’s construction and an amusing anecdote about
+the name.
+I doubt there are more than twelve people on the planet who care about
+this kind of parsing arcana.
+<i>[Rick Jelliffe
+<a href="http://www.oreillynet.com/xml/blog/2006/04/xml_in_xml.html">has
+upgraded</a> the machine].</i></p>
+<h2 id='p-1'>Why “Lark”?</h2>
+<p><a href="http://www.laurenwood.org/anyway/">Lauren</a> and I went to
+Australia in late 1996 to visit her mother and to get married, which we
+did on November 30th. Forty-eight hours later, Lauren twisted her knee
+badly enough that she was pretty well
+confined to a sofa for the rest of our Australian vacation.</p>
+<p>So I broke out my computer and finished the work I’d already started on my
+XML processor, and decided to call it Lark for <b>La</b>uren’s <b>R</b>ight
+<b>K</b>nee.</p>
+<h2 id='p-2'>How Lark Worked</h2>
+<p>Lark was a pure
+<a href="http://en.wikipedia.org/wiki/Deterministic_finite_state_machine">deterministic
+finite automaton</a> (DFA)
+parser, with a little teeny state stack.
+Some of its transitions were labeled with named “events” that would provoke
+the parser to do something if, for example, it had just recognized a start tag
+or whatever.</p>
+<p>DFA-driven parsers are a common enough design pattern, although I think
+Lark is the only example in the XML space.
+There are well-known parser generators such as
+<a href="http://en.wikipedia.org/wiki/Yacc">yacc</a>,
+<a href="http://en.wikipedia.org/wiki/GNU_bison">GNU bison</a>, and
+<a href="https://javacc.dev.java.net/">javacc</a>,
+usually used in combination with lexical scanners such as
+<a href="http://en.wikipedia.org/wiki/Flex_lexical_analyser">flex</a> so that
+you can write your grammar in terms of tokens not characters.
+Also, they handle LALR langauges, so the parsing technique is quite a bit
+richer than a pure state machine.</p>
+<p>I thought I had a better idea. The grammar of XML is simple
+enough, and the syntax characters few enough, that I thought I could just
+write down the state machine by hand.
+So that’s what I did, inventing a special-purpose DFA-description
+language for the purpose.</p>
+<p>Then I had a file called <code>Lark.jin</code> which was really a Java
+program that used the state machine to parse XML. The transition “events”
+in the machine were mapped to <code>case</code> labels in a huge
+<code>switch</code> construct. Then there was a horrible, <em>horrible</em>
+Perl program that read the <code>Lark.jin</code> and the automaton,
+generated the DFA tables in Java syntax, inserted them into the code and
+produced <code>Lark.java</code>, which you actually compiled
+to make the parser.</p>
+<p>So while Java doesn’t have a preprocessor, Lark did, which made quite a few
+things easier.</p>
+<p>There were a lot of tricks; some of the state transitions
+weren’t on characters, they were on XML character classes such as
+<code>NameChar</code> and so on.
+This made the automaton easier to write, and in fact, to keep the class files
+small, the character-class transitions persisted into the Java form, and the
+real DFA was built at startup time.
+These days, quick startup might be more important than <code>.class</code>
+file size.</p>
+<h2 id='p-3'>What Was Good</h2>
+<p>It was <em>damn</em> fast. James Clark managed to hand-craft a
+Java-language XML parser called
+<a href="http://jclark.com/xml/xp/index.html">XP</a> that was a little faster
+than Lark, but he did that by clever I/O buffering, and I was determined to
+leapfrog him by improving my I/O.</p>
+<p>This was before the time of standardized XML APIs, but Lark had a stream API
+that influenced SAX, and a DOM-like tree API; both worked just fine.
+Lark is one of very few parsers ever to have survived the
+<a href="http://www.securityfocus.com/archive/1/303509/2002-12-13/2002-12-19/0">billion
+laughs attack</a>.</p>
+<p>Lark was put into production in quite a few deployments, and the flow of
+bug reports slowed to a trickle.
+Then in 1998 I noticed that IBM and Microsoft and BEA and everyone else
+were building XML Processors, so I decided that it wasn’t worthwhile
+maintaining mine.</p>
+<h2 id='p-4'>What Was Bad</h2>
+<p>I never got around to teaching it namespaces, which means it wouldn’t be
+real useful today.</p>
+<p>It had one serious bug that would have been real work to fix and since
+nobody ever encountered it in practice, I kept putting it off and never did.
+If you had an internal parsed entity reference in an attribute value and the
+replacement text included the attribute delimiter (<code>'</code> or
+<code>"</code>), it would scream and claim you had a busted XML document.</p>
+<h2 id='p-5'>That Automaton</h2>
+<p>What happened was,
+<a href="http://www.oreillynet.com/pub/au/1712">Rick Jelliffe</a>, who is a
+Good Person, was
+<a href="http://www.stylusstudio.com/xmldev/200604/post30110.html">looking for
+a FSM for XML</a> and I eventually noticed, and so I sent him mine.</p>
+<p>There’s no reason whatsoever to keep it a secret:
+<a href="/ongoing/code/lark/com/textuality/autom.txt">here it is</a>.
+Be warned: it’s ugly.</p>
+<p>Fortunately, there were only 227 states and 8732 transitions, so the state
+number fit into a
+byte; that and the associated event index pack into a short.
+To make things even tighter, the transitions were only keyed by characters up
+to 127, as in 7-bit ASCII.
+Characters higher than that can’t be XML syntax characters, so we’re only
+interested whether they fall into classes like <code>NameChar</code> and
+<code>NameStartChar</code> and so on. A 64K <code>byte[]</code> array takes
+care of that, each byte having a class bitmask.</p>
+<p>As a result of all this jiggery-pokery, the DFA ends up, believe it
+or not, constituting a <code>short[227][128]</code>.</p>
+<p>Here’s a typical chunk of the automaton:</p>
+<pre><code>1. # in Start tag GI
+2. State StagGI BustedMarkup {in element type}
+3. T $NameC StagGI
+4. T $S InStag !EndGI
+5. T > InDoc !EndGI !ReportSTag
+6. T / EmptyClose !EndGI</code></pre>
+<p>This state, called <code>StagGI</code>, is the state where we’re actually
+reading the name of a tag, we got here by seeing a <code>&lt;</code> followed
+by a <code>NameStart</code> character.<br/>
+Line 1 is a comment.<br/>
+In line 2 we name the state, and support error reporting, providing the name
+of another state to fall back into in case of error, and in the curly braces,
+some text to help build an error message.<br/>
+Line 3 says that if we see a valid XML Name character, we just stay in this
+state.<br/>
+Line 4 says that if we see an XML space character, we move to state
+<code>InStag</code> and process an <code>EndGI</code> event, which would stash
+the characters in the start tag.<br/>And so on.</p>
+<h2 id='p-6'>Other Hackery</h2>
+<p>An early cut of Lark used String and StringBuffer objects to hold all the
+bits and pieces of the XML. This might be a viable strategy today, but in
+1996’s Java it was painfully slow.
+So the code goes to heroic lengths to live in the land of character arrays at
+all times, making Strings only when a client program asks for one through the
+API. The performance difference was mind-boggling.</p>
+<h2 id='p-7'>An Evil Idea</h2>
+<p>If you look at the automaton, and the Lark code, at least half—I’d bet
+three quarters—is there to deal with parsing the DTD and then dealing with
+entity wrangling.
+A whole bunch more is there to support DOM-building and walking.</p>
+<p>I bet if I went through and simply removed support for anything coming out
+of the <code>&lt;!DOCTYPE></code>, including all entity processing,
+then discarded
+the DOM stuff, then added namespace support and SAX and StAX APIs, it would be
+less than half its current size.
+Then if I reworked the I/O, knowing what I know now and stealing some tricks
+that James Clark uses in
+<a href="http://expat.sourceforge.net/">expat</a>, I bet it would
+be the fastest Java XML parser on the planet for XML docs without a
+DOCTYPE; by a wide margin. It’s hard to beat a DFA.</p>
+<p>And it would still be fully XML 1.0 compliant. Because (snicker) this is
+Java, and your basic core Java now includes an XML parser, so I could simply
+instrument Larkette to buffer the prologue and if it saw a DOCTYPE with an
+internal subset, defer to Java’s built-in parser.</p>
+<p>I’ll probably never do it. But the thought brings a smile to my face.</p>
+</div></content></entry>
+
+<entry xml:base='When/200x/2006/04/22/'>
+ <title>Just A Kid</title>
+ <link href='Just-a-Kid' />
+ <id>http://www.tbray.org/ongoing/When/200x/2006/04/22/Just-a-Kid</id>
+ <published>2006-04-22T13:00:00-08:00</published>
+ <updated>2006-04-22T13:37:58-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='The World/Food and Drink' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='The World' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Food and Drink' />
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p>Last weekend, Lauren felt like cooking up home-made Easter eggs, so
+the shopping list included “chocolate chips (large bag)”. I was heading down
+the bulk-foods aisle and realized one of the vertical acrylic bins was full of
+them. Someone had been sloppy, and there was a little heap of chocolate chips
+on the shelf underneath it. For a second, I flashed into pure eight-year-old
+mode, thinking “Holy cow, there’s a <em>whole bin</em> full of chocolate
+chips, and more just lying there!” I popped a few in my mouth and they were
+excellent; semi-sweet, dark, strong, and firm. I was still in the state that
+Buddhists don’t mean when they say “Child’s Mind”, thinking “I
+can get as many as I want!” The list did say “large bag” after all, so I put
+a bag under the spout and gleefully jammed the lever <em>all the way
+over</em>. At home, Lauren said “You went overboard, a bit, didn’t you?”
+and now we have a plastic canister-full in the pantry which should last us
+into 2007. It’s a good feeling.</p>
+</div></content></entry>
+
+<entry xml:base='When/200x/2006/04/22/'>
+ <title>Goddess</title>
+ <link href='Goddess' />
+ <id>http://www.tbray.org/ongoing/When/200x/2006/04/22/Goddess</id>
+ <published>2006-04-22T13:00:00-08:00</published>
+ <updated>2006-04-22T12:25:59-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='The World/Family' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='The World' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Family' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology/Microsoft' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Microsoft' />
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p>That would be my wife
+<a href="http://www.laurenwood.org/anyway/">Lauren</a>. After
+<a href="/ongoing/When/200x/2006/04/16/Mad-at-Microsoft">I b0rked</a> our
+Win2K gamebox, I tried re-installing the OS and eventually reduced it to
+complete brick-ness, it recognized neither the video adapter nor the network
+card. So Lauren brushed me aside and started wrestling with the problem, and
+to make a long story short, it almost completely works again. At one point
+she seemed nearly infinite in her capabilities, sitting in front of the
+computer wrangling software updates while knitting baby stuff and looking up
+words in a German dictionary for the kid’s homework. Some of the German nouns
+and muttered curses at the Windows install sounded remarkably like each other.
+Why would anyone not marry a geek? The only problem is that Win2K won’t
+auto-switch resolutions to play games any more, it gets the frequency wrong
+and the LCD goes pear-shaped, you have to hand-select the frequency and
+switch into the right resolution first. LazyWeb?</p>
+</div></content></entry>
+
+<entry xml:base='When/200x/2006/04/21/'>
+ <title>Routing Around Spotlight</title>
+ <link href='Routing-Around-Spotlight' />
+ <id>http://www.tbray.org/ongoing/When/200x/2006/04/21/Routing-Around-Spotlight</id>
+ <published>2006-04-21T13:00:00-08:00</published>
+ <updated>2006-04-21T23:16:25-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology/Mac OS X/Gripes' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Mac OS X' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Gripes' />
+ <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>Herewith two hideously ugly little shell scripts for use when Spotlight refuses to search your mail. Spotlight is a flawed v1.0 implementation of a really good idea and will, I&#x2019;m sure, be debugged in a near-future release. <i>[Update: The LazyWeb is educating me... these are moving targets.]</i></div></summary>
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p>Herewith two hideously ugly little shell scripts for use when Spotlight
+refuses to search your mail.
+Spotlight is a flawed v1.0 implementation of a really good idea and will, I’m
+sure, be debugged in a near-future release.
+<i>[Update: The LazyWeb is educating me... these are moving targets.]</i></p>
+<p>My problem is that whereas Mail.app will search my To/From/Subject
+lines (slowly, and with a
+<a href="/ongoing/When/200x/2005/11/20/UnTiger">really irritating GUI</a>),
+the “Entire Message” option just doesn’t work, it returns instantly with no
+results. Yes, I’ve read the hints about making Spotlight re-index,
+but it just flatly refuses to work for me. Mind you, I have a lot of
+email, but still, it should at least try.</p>
+<p>It turns out I had never really figured out the <code>-print0</code> and
+<code>-0</code> idioms that a lot of the shell-command stalwarts now have.
+Thanks to Malcolm Tredinnick for raising my consciousness.</p>
+<p>This lives in <code>$HOME/bin</code> under the name
+<code>mailgrep</code>:</p>
+<pre><code>#!/bin/sh
+find $HOME/Library/Mail/IMAP* -name '*.emlx' -print0 | \
+ xargs -0 fgrep -i $@</code></pre>
+<p>Isn’t <code>xargs</code> a funny command? I’ve discovered that it’s nearly
+impossible to describe what does, and then why what it does is necessary, but
+there are just a whole bunch of places where you’d be lost without it.</p>
+<p>This lives in <code>$HOME/bin/mailview</code>:</p>
+<pre><code>#!/bin/sh
+find $HOME/Library/Mail/IMAP* -name '*.emlx' -print0 | \
+ xargs -0 fgrep -i -l -Z $@ | \
+ xargs -0 open</code></pre>
+<p>The first cut of this dodged <code>xargs</code> and used an
+incredibly-inefficient and slow chain of <code>-exec</code> arguments to open
+the files one at a time with
+<code>view</code> (aka <code>vim</code>), to work around
+a well-known <code>vim</code> misfeature; it complained about the input
+not being a terminal and left my Terminal.app keystrokes borked.</p>
+<p>But Malcolm, confirming my belief in the broken-ness of <code>vim</code>,
+said “Oh, *that* ‘view’. I thought it was some sexy Mac ‘view my email’ app”.
+D’oh, of course; the magic OS X <code>open</code> command does just the right
+thing.
+Erm, you might want to run <code>mailgrep</code> before you run
+<code>mailview</code>; I’m not sure what would happen if you asked OS X to
+open three or four thousand email messages at once.</p>
+</div></content></entry>
+
+<entry xml:base='When/200x/2006/04/21/'>
+ <title>FSS: Pink Flowers</title>
+ <link href='Dracon-Help' />
+ <id>http://www.tbray.org/ongoing/When/200x/2006/04/21/Dracon-Help</id>
+ <published>2006-04-21T13:00:00-08:00</published>
+ <updated>2006-04-21T17:19:27-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Arts/Photos' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Arts' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Photos' />
+ <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>Friday Slide Scan #28 is two Eighties florals, one interior, one exterior. With a confession.</div></summary>
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p>Friday Slide Scan #28 is two Eighties florals, one interior, one
+exterior. With a confession.</p>
+<p>First some spring flowers fallen from a tree, just as now in our front
+yard, at dusk.</p>
+<img src="0506.png" alt="Fallen pink treeflowers on grass at dusk" />
+<p>I’m not sure what these are, but look at the light in the center. Rewards
+enlarging.</p>
+<img src="0713.png" alt="Flowers in shadow with light in background" />
+<p>Here’s the confession. Sometimes on Fridays when I’m feeling kinda
+burned-out, I knock off work and do these slide scans in the office, because
+this is where I have the
+<a href="http://www.tbray.org/ongoing/When/200x/2004/04/14/MineIsBigger">big
+screen</a>.
+Blowing these pictures up to mega-huge, picking away at the old-slide crud and
+scanning artifacts, tinkering with the colour balance, and listening; I never
+play music while I’m writing or coding seriously, but I play it real loud while
+photo-editing. It’s all pretty well pure pleasure; you just can’t imagine
+how good that second one above looks at near-native size.
+It reconstitutes the part of my mind that I earn my living with; that’s my
+story and I’m sticking to it.</p>
+<p>Images in the Friday Slide Scans are from 35mm slides taken between 1953
+and 2003 by (in rough chronological order)
+<a href="http://www.textuality.com/BillBray/">Bill Bray</a>,
+<a href="/ongoing/When/200x/2004/08/11/MomsGarden">Jean Bray</a>, Tim Bray, Cath
+Bray, and
+<a href="http://www.laurenwood.org/anyway/">Lauren Wood</a>; when I know
+exactly who took one, I’ll say; in this case, at least one is by Cath Bray.
+Most but not all of the slides were on Kodachrome; they were digitized using
+a Nikon CoolScan 4000 ED scanner and cleaned up by a combination of the Nikon
+scanning software and PhotoShop Elements.</p>
+</div></content></entry>
+
+<entry xml:base='When/200x/2006/04/20/'>
+ <title>Spring Pix</title>
+ <link href='Spring-Pix' />
+ <id>http://www.tbray.org/ongoing/When/200x/2006/04/20/Spring-Pix</id>
+ <published>2006-04-20T13:00:00-08:00</published>
+ <updated>2006-04-20T23:07:10-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='The World/Places/Vancouver' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='The World' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Places' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Vancouver' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Arts/Photos' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Arts' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Photos' />
+ <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>Three pictures around Vancouver; one of a fresh green springtime tree, two of rotten old buildings being torn down.</div></summary>
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p>Three pictures around Vancouver; one of a fresh green springtime tree, two
+of rotten old buildings being torn down.</p>
+<p>There’s nothing quite as fresh as just-sprouted deciduous leaves;
+another few weeks and this tree will be just a tree.</p>
+<img src="IMG_4656.png" alt="Sunlit fresh young leaves" />
+<p>I have a thing about demolition.
+The first is a rotten dingy old one-story on Main Street near 23rd, the second
+is an unlovely grey mid-rise being torn down to build still more condos at
+Homer and Helmcken.</p>
+<img src="IMG_4665.png" alt="Demolition site on Main Street, Vancouver" />
+<img src="IMG_4671.png" alt="Demolition site at Homer and Helmcken, Vancouver" />
+</div></content></entry>
+
+<entry xml:base='When/200x/2006/04/20/'>
+ <title>Totten&#x2019;s Trip</title>
+ <link href='Totten-on-Iraq' />
+ <id>http://www.tbray.org/ongoing/When/200x/2006/04/20/Totten-on-Iraq</id>
+ <published>2006-04-20T13:00:00-08:00</published>
+ <updated>2006-04-20T21:05:22-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='The World/Places/Middle East' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='The World' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Places' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Middle East' />
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p><a href="http://www.michaeltotten.com/">Michael J. Totten</a> is a
+journalist and blogger who’s back and forth to the
+Middle East and writes about it, quite well in my opinion; he supports this by
+freelancing and with his blog’s tip jar. He gets lots of
+link love from the right-wing blogosphere, which is puzzling because Totten is
+balanced and clear-eyed and doesn’t seem to have any particular axe to grind.
+Recently, he and a friend were
+<a href="http://www.michaeltotten.com/archives/001117.html">having fun in
+Istanbul</a> and, on a random drive out into the country, decided on impulse to
+keep going, all the way across Turkey and into Iraq; into the Kurdish
+mini-state in Iraq’s north, to
+be precise. It makes a heck of a story, with lots of pictures, in six parts:
+<a href="http://www.michaeltotten.com/archives/001119.html">I</a>,
+<a href="http://www.michaeltotten.com/archives/001120.html">II</a>,
+<a href="http://www.michaeltotten.com/archives/001121.html">III</a>,
+<a href="http://www.michaeltotten.com/archives/001124.html">IV</a>,
+<a href="http://www.michaeltotten.com/archives/001126.html">V</a>, and
+<a href="http://www.michaeltotten.com/archives/001127.html">VI</a>.
+</p>
+</div></content></entry>
+
+<entry xml:base='When/200x/2006/04/19/'>
+ <title>The Cost of AJAX</title>
+ <link href='The-Cost-of-AJAX' />
+ <id>http://www.tbray.org/ongoing/When/200x/2006/04/19/The-Cost-of-AJAX</id>
+ <published>2006-04-19T13:00:00-08:00</published>
+ <updated>2006-04-20T00:37:46-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology/Web' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Technology' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Web' />
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p>James Governor
+<a href="http://www.redmonk.com/jgovernor/archives/001526.html">relays a
+question</a> that sounds important
+but I think is actively dangerous: do AJAX apps present more of
+a server-side load? The question is dangerous because it’s meaningless and
+unanswerable. Your typical Web page will, in the process of
+loading, call back to the server for a bunch of stylesheets and graphics and
+scripts and so on: for example, this <span class='o'>ongoing</span> page calls
+out to three different graphics, one stylesheet, and one JavaScript file.
+It also has one “AJAXy” XMLHttpRequest call.
+From the server’s point of view, those are all just requests to dereference
+one URI or another. In the case
+of <span class='o'>ongoing</span>, the AJAX request is for a static file less
+than 200 bytes in size (i.e. cheap).
+On the other hand, it could have been for something that required a
+complex outer join on two ten-million-row tables (i.e. <em>very</em>
+expensive). And one of the virtues of
+the Web Architecture is that it hides those differences, the “U” in URI stands
+for “Uniform”, it’s a Uniform interface to a resource on the Web that could
+be, well, anything.
+So saying “AJAX is expensive” (or that it’s cheap) is like saying “A mountain
+bike is slower than a battle tank” (or that it’s faster).
+The truth depends on what you’re doing with it.
+In the case of web sites, it depends on how many fetches you do and
+where you have to go to get the data to satisfy them.
+<span class='o'>ongoing</span> is a pretty quick web site, even though it runs
+on a fairly modest server, but
+that has nothing to do with AJAX-or-not; it’s because of the particular way
+I’ve set up the Web resources that make the pages here.
+I’ve
+<a href="/ongoing/When/200x/2006/02/14/AJAX-Performance">argued elsewhere</a>
+that AJAX can be a performance win, system-wide; but that argument too is
+contingent on context, lots of context.</p>
+</div></content></entry>
+
+<entry xml:base='When/200x/2006/04/18/'>
+ <title>Hao Wu and Graham McMynn</title>
+ <link href='Hao-Wu' />
+ <id>http://www.tbray.org/ongoing/When/200x/2006/04/18/Hao-Wu</id>
+ <published>2006-04-18T13:00:00-08:00</published>
+ <updated>2006-04-18T22:00:40-08:00</updated>
+ <category scheme='http://www.tbray.org/ongoing/What/' term='The World/Places/China' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='The World' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Places' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='China' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='The World/Politics' />
+ <category scheme='http://www.tbray.org/ongoing/What/' term='Politics' />
+<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
+<p>Graham McMynn is a teenager who was kidnapped in Vancouver on April 4th and
+freed, in a large, noisy, and
+<a href="http://www.cbc.ca/story/news/national/2006/04/12/bcabduction060412.html">newsworthy</a>
+police operation, on April 12th.
+<a href="http://en.wikipedia.org/wiki/Hao_Wu">Hao Wu</a> is a Chinese
+film-maker and
+<a href="http://beijingorbust.blogspot.com/">blogger</a> who was kidnapped in
+Beijing on February 22nd in a
+small, quiet police operation not intended to be newsworthy, and who has not
+been freed.
+Read about it
+<a href="http://spaces.msn.com/wuhaofamily/">here</a>,
+<a href="http://ethanzuckerman.com/haowu/">here</a>, and
+<a href="http://rconversation.blogs.com/rconversation/freehaowu/index.html">here</a>.
+Making noise about it <em>might</em> influence the government of China to
+moderate its actions against Mr. Wu, and can’t do any harm.
+Mr. McMynn’s kidnappers were a gaggle of small-time hoodlums, one of whom was
+out on bail while awaiting trial for another kidnapping (!).
+Mr. Wu’s were police.
+In a civilized country, the function of the police force is to deter such
+people and arrest them. A nation where they are the same people? Nobody
+could call it “civilized”.</p>
+</div></content></entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_title_xhtml.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_title_xhtml.xml
new file mode 100644
index 000000000..0b4d21b96
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_title_xhtml.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom title works
+Expect: feed.title.plainText() == 'test title'
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+ <title type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml"><b>test</b> title</div>
+ </title>
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_title_xhtml_entities.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_title_xhtml_entities.xml
new file mode 100644
index 000000000..aaf982acf
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_title_xhtml_entities.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom summary with entities works
+Expect: feed.subtitle.text == '&quot;test&quot; &amp; &apos;title&apos; &amp; &lt;ok&gt;'
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+<subtitle type="xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml">
+ "test&quot; &amp; &apos;title' &amp; &lt;ok>
+ </div>
+</subtitle>
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_updated.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_updated.xml
new file mode 100644
index 000000000..f425674f2
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_updated.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: raw atom updated works
+Expect: feed.fields.getProperty('atom:updated') == '2003-12-13T18:30:02Z'
+
+-->
+
+<feed xmlns="http://www.w3.org/2005/Atom">
+
+ <title>Example Feed</title>
+ <link href="http://example.org/"/>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <author>
+ <name>John Doe</name>
+ </author>
+ <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+
+ <entry>
+ <title>Atom-Powered Robots Run Amok</title>
+ <link href="http://example.org/2003/12/13/atom03"/>
+ <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <summary>Some text.</summary>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_updated_invalid.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_updated_invalid.xml
new file mode 100644
index 000000000..560d756b9
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_updated_invalid.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: non-date atom updated should produce null feed.updated
+Expect: feed.updated == null
+
+-->
+
+<feed xmlns="http://www.w3.org/2005/Atom">
+
+ <title>Example Feed</title>
+ <link href="http://example.org/"/>
+ <updated>2003I'mNotADate</updated>
+ <author>
+ <name>John Doe</name>
+ </author>
+ <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+
+ <entry>
+ <title>Atom-Powered Robots Run Amok</title>
+ <link href="http://example.org/2003/12/13/atom03"/>
+ <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <summary>Some text.</summary>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_updated_normalized.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_updated_normalized.xml
new file mode 100644
index 000000000..71fa1d03d
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_updated_normalized.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom updated works
+Expect: feed.updated == 'Sat, 13 Dec 2003 18:30:02 GMT'
+
+-->
+
+<feed xmlns="http://www.w3.org/2005/Atom">
+
+ <title>Example Feed</title>
+ <link href="http://example.org/"/>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <author>
+ <name>John Doe</name>
+ </author>
+ <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
+
+ <entry>
+ <title>Atom-Powered Robots Run Amok</title>
+ <link href="http://example.org/2003/12/13/atom03"/>
+ <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
+ <updated>2003-12-13T18:30:02Z</updated>
+ <summary>Some text.</summary>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_version.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_version.xml
new file mode 100644
index 000000000..a703f506f
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_version.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 Version works
+Expect: result.version == 'atom'
+-->
+<feed xmlns="http://www.w3.org/2005/Atom">
+
+</feed> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rfc4287/feed_xmlBase.xml b/toolkit/components/feeds/test/xml/rfc4287/feed_xmlBase.xml
new file mode 100644
index 000000000..d5760e333
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rfc4287/feed_xmlBase.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: atom feed with xml:base
+Expect: feed.link.spec == "http://www.example.com/foo/bar/baz";
+
+-->
+<feed xmlns="http://www.w3.org/2005/Atom"
+ xml:base="http://www.example.com/foo/bar/">
+
+ <id>tag:example.com,2006:/atom/conformance/linktest/</id>
+ <title>Atom Link Tests</title>
+ <updated>2005-06-18T16:13:00Z</updated>
+ <link href="baz" />
+
+ <entry xml:base="http://www.example.org">
+ <id>tag:example.org,2006:/linkreltest/1</id>
+ <title>Does your reader support xml:base properly? </title>
+ <updated>2006-06-23T12:12:12Z</updated>
+ <link xml:base="/bar/" href="foo"/>
+ </entry>
+
+</feed>
diff --git a/toolkit/components/feeds/test/xml/rss09x/rss090.xml b/toolkit/components/feeds/test/xml/rss09x/rss090.xml
new file mode 100644
index 000000000..783c018f4
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss09x/rss090.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<!--
+
+Description: RSS 0.90 works
+Expect: feed.title.plainText() == "Mozilla Dot Org" && result.version == "rss090"
+
+-->
+<!-- The very first RSS file, circa 1999 -->
+<rdf:RDF
+xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+xmlns="http://my.netscape.com/rdf/simple/0.9/">
+
+ <channel>
+ <title>Mozilla Dot Org</title>
+ <link>http://www.mozilla.org</link>
+ <description>the Mozilla Organization web site</description>
+ </channel>
+
+ <image>
+ <title>Mozilla</title>
+ <url>http://www.mozilla.org/images/moz.gif</url>
+ <link>http://www.mozilla.org</link>
+ </image>
+
+ <item>
+ <title>New Status Updates</title>
+ <link>http://www.mozilla.org/status/</link>
+ </item>
+
+ <item>
+ <title>Bugzilla Reorganized</title>
+ <link>http://www.mozilla.org/bugs/</link>
+ </item>
+
+ <item>
+ <title>Mozilla Party, 2.0!</title>
+ <link>http://www.mozilla.org/party/1999/</link>
+ </item>
+
+ <item>
+ <title>Unix Platform Parity</title>
+ <link>http://www.mozilla.org/build/unix.html</link>
+ </item>
+
+ <item>
+ <title>NPL 1.0M published</title>
+ <link>http://www.mozilla.org/NPL/NPL-1.0M.html</link>
+ </item>
+
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss09x/rss091.xml b/toolkit/components/feeds/test/xml/rss09x/rss091.xml
new file mode 100644
index 000000000..6749fc49e
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss09x/rss091.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<!DOCTYPE rss SYSTEM "http://my.netscape.com/publish/formats/rss-0.91.dtd">
+<!--
+
+Description: RSS 0.91 works
+Expect: feed.title.plainText() == "Scripting News" && result.version == "rss091"
+
+-->
+<rss version="0.91">
+ <channel>
+ <language>en</language>
+ <description>
+ News and commentary from the cross-platform scripting community.
+ </description>
+ <link>http://www.scripting.com/</link>
+ <title>Scripting News</title>
+ <image>
+ <link>http://www.scripting.com/</link>
+ <title>Scripting News</title>
+ <url>http://www.scripting.com/gifs/tinyScriptingNews.gif</url>
+ </image>
+ <item>
+ <title>stuff</title>
+ <link>http://bar.example.com</link>
+ <description>This is an article about some stuff</description>
+ </item>
+ </channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss09x/rss091_withNS.xml b/toolkit/components/feeds/test/xml/rss09x/rss091_withNS.xml
new file mode 100644
index 000000000..9ab2c3bf7
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss09x/rss091_withNS.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<!DOCTYPE rss SYSTEM "http://my.netscape.com/publish/formats/rss-0.91.dtd">
+<!--
+
+Description: RSS 0.91 works
+Expect: feed.title.plainText() == "Scripting News" && result.version == "rss091"
+
+-->
+<rss version="0.91" xmlns="http://backend.userland.com/RsS2">
+ <channel>
+ <language>en</language>
+ <description>
+ News and commentary from the cross-platform scripting community.
+ </description>
+ <link>http://www.scripting.com/</link>
+ <title>Scripting News</title>
+ <image>
+ <link>http://www.scripting.com/</link>
+ <title>Scripting News</title>
+ <url>http://www.scripting.com/gifs/tinyScriptingNews.gif</url>
+ </image>
+ <item>
+ <title>stuff</title>
+ <link>http://bar.example.com</link>
+ <description>This is an article about some stuff</description>
+ </item>
+ </channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss09x/rss092.xml b/toolkit/components/feeds/test/xml/rss09x/rss092.xml
new file mode 100644
index 000000000..ed68bd64f
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss09x/rss092.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!--
+
+Description: RSS 0.92 works
+Expect: feed.title.plainText() == "Scripting News" && result.version == "rss092"
+
+-->
+<rss version="0.92">
+ <channel>
+ <language>en</language>
+ <description>
+ News and commentary from the cross-platform scripting community.
+ </description>
+ <link>http://www.scripting.com/</link>
+ <title>Scripting News</title>
+ <image>
+ <link>http://www.scripting.com/</link>
+ <title>Scripting News</title>
+ <url>http://www.scripting.com/gifs/tinyScriptingNews.gif</url>
+ </image>
+ <item>
+ <title>stuff</title>
+ <link>http://bar.example.com</link>
+ <description>This is an article about some stuff</description>
+ </item>
+ </channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss09x/rss093.xml b/toolkit/components/feeds/test/xml/rss09x/rss093.xml
new file mode 100644
index 000000000..f1bb81ddf
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss09x/rss093.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!--
+
+Description: RSS 0.93 works
+Expect: feed.title.plainText() == "Scripting News" && result.version == "rss093"
+
+-->
+<rss version="0.93">
+ <channel>
+ <language>en</language>
+ <description>
+ News and commentary from the cross-platform scripting community.
+ </description>
+ <link>http://www.scripting.com/</link>
+ <title>Scripting News</title>
+ <image>
+ <link>http://www.scripting.com/</link>
+ <title>Scripting News</title>
+ <url>http://www.scripting.com/gifs/tinyScriptingNews.gif</url>
+ </image>
+ <item>
+ <title>stuff</title>
+ <link>http://bar.example.com</link>
+ <description>This is an article about some stuff</description>
+ </item>
+ </channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss09x/rss094.xml b/toolkit/components/feeds/test/xml/rss09x/rss094.xml
new file mode 100644
index 000000000..1c2b17a24
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss09x/rss094.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!--
+
+Description: RSS 0.94 works
+Expect: feed.title.plainText() == "Scripting News" && result.version == "rss094"
+
+-->
+<rss version="0.94">
+ <channel>
+ <language>en</language>
+ <description>
+ News and commentary from the cross-platform scripting community.
+ </description>
+ <link>http://www.scripting.com/</link>
+ <title>Scripting News</title>
+ <image>
+ <link>http://www.scripting.com/</link>
+ <title>Scripting News</title>
+ <url>http://www.scripting.com/gifs/tinyScriptingNews.gif</url>
+ </image>
+ <item>
+ <title>stuff</title>
+ <link>http://bar.example.com</link>
+ <description>This is an article about some stuff</description>
+ </item>
+ </channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss09x/rssUnknown.xml b/toolkit/components/feeds/test/xml/rss09x/rssUnknown.xml
new file mode 100644
index 000000000..653b574d0
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss09x/rssUnknown.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!--
+
+Description: RSS unknown version works
+Expect: feed.title.plainText() == "Scripting News" && result.version == "rssUnknown"
+
+-->
+<rss version="0.95">
+ <channel>
+ <language>en</language>
+ <description>
+ News and commentary from the cross-platform scripting community.
+ </description>
+ <link>http://www.scripting.com/</link>
+ <title>Scripting News</title>
+ <image>
+ <link>http://www.scripting.com/</link>
+ <title>Scripting News</title>
+ <url>http://www.scripting.com/gifs/tinyScriptingNews.gif</url>
+ </image>
+ <item>
+ <title>stuff</title>
+ <link>http://bar.example.com</link>
+ <description>This is an article about some stuff</description>
+ </item>
+ </channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/feed_bogus_title.xml b/toolkit/components/feeds/test/xml/rss1/feed_bogus_title.xml
new file mode 100644
index 000000000..a28952495
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/feed_bogus_title.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed w/ bogus title element
+Expect: feed.title.text == 'Correct Title'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+
+
+
+ <title>Bogus</title>
+
+
+
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Correct Title</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ </channel>
+
+
+
+ <title>Bogus</title>
+
+
+
+ <item>
+ <title>XML: A Disruptive Technology</title>
+ <link>http://c.moreover.com/click/here.pl?r123</link>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical infrastructure of the Internet.
+ </dc:description>
+ </item>
+ <item>
+ <dc:publisher>The O'Reilly Network</dc:publisher>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical infrastructure of the Internet 2.
+ </dc:description>
+ <title>XML: A Disruptive Technology</title>
+ </item>
+</rdf:RDF>
diff --git a/toolkit/components/feeds/test/xml/rss1/feed_description.xml b/toolkit/components/feeds/test/xml/rss1/feed_description.xml
new file mode 100644
index 000000000..109b8f949
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/feed_description.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed description works
+Expect: feed.fields.getProperty('rss1:description') == 'a description'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <description>a description</description>
+ </channel>
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/feed_description_normalized.xml b/toolkit/components/feeds/test/xml/rss1/feed_description_normalized.xml
new file mode 100644
index 000000000..44154b9f1
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/feed_description_normalized.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed description works normalized
+Expect: feed.subtitle.text == 'a description'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <description>a description</description>
+ </channel>
+</rdf:RDF>
diff --git a/toolkit/components/feeds/test/xml/rss1/feed_description_with_dc.xml b/toolkit/components/feeds/test/xml/rss1/feed_description_with_dc.xml
new file mode 100644
index 000000000..4e5b1637a
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/feed_description_with_dc.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed description works normalized
+Expect: feed.subtitle.text == 'a description'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'
+>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ <description>a description</description>
+ </channel>
+</rdf:RDF>
diff --git a/toolkit/components/feeds/test/xml/rss1/feed_description_with_dc_only.xml b/toolkit/components/feeds/test/xml/rss1/feed_description_with_dc_only.xml
new file mode 100644
index 000000000..fa1ecd59a
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/feed_description_with_dc_only.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed description works normalized
+Expect: feed.subtitle.plainText() == 'another description'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ </channel>
+</rdf:RDF>
diff --git a/toolkit/components/feeds/test/xml/rss1/feed_generator.xml b/toolkit/components/feeds/test/xml/rss1/feed_generator.xml
new file mode 100644
index 000000000..07ec85321
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/feed_generator.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+
+Description: RSS1 generator
+Expect: feed.generator.agent == "http://Orchard.SourceForge.net/1.2/"
+
+-->
+
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:admin="http://webns.net/mvcb/"
+ xmlns="http://purl.org/rss/1.0/">
+
+ <channel rdf:about="http://meerkat.oreillynet.com/?_fl=rss1.0">
+ <title>Meerkat</title>
+ <link>http://meerkat.oreillynet.com</link>
+ <description>Meerkat: An Open Wire Service</description>
+ <admin:errorReportsTo rdf:resource="mailto:channel-owner@acme.orgs"/>
+ <admin:generatorAgent rdf:resource="http://Orchard.SourceForge.net/1.2/"/>
+
+ <image rdf:resource="http://meerkat.oreillynet.com/icons/meerkat-powered.jpg" />
+
+ <items>
+ <rdf:Seq>
+ <rdf:li rdf:resource="http://c.moreover.com/click/here.pl?r123" />
+ </rdf:Seq>
+ </items>
+
+ <textinput rdf:resource="http://meerkat.oreillynet.com/" />
+
+ </channel>
+
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/feed_id.xml b/toolkit/components/feeds/test/xml/rss1/feed_id.xml
new file mode 100644
index 000000000..8f118102a
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/feed_id.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed w/ feed rdf:about
+Expect: feed.id == 'http://www.xml.com/xml/news.rss'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ </channel>
+ <item rdf:about="http://example.com/hmm">
+ <title>XML: A Disruptive Technology</title>
+ <link>http://c.moreover.com/click/here.pl?r123</link>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical
+ infrastructure of the Internet.
+ </dc:description>
+ </item>
+</rdf:RDF>
diff --git a/toolkit/components/feeds/test/xml/rss1/feed_image.xml b/toolkit/components/feeds/test/xml/rss1/feed_image.xml
new file mode 100644
index 000000000..c293acc3f
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/feed_image.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed w/ image
+Expect: ((feed.image.getProperty('rss1:link') == 'http://www.xml.com') && (feed.image.getProperty('rss1:url') == 'http://xml.com/universal/images/xml_tiny.gif'))
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ <textInput rdf:resource="http://www.google.com"/>
+ </channel>
+
+ <image rdf:about="http://xml.com/universal/images/xml_tiny.gif">
+ <title>XML.com</title>
+ <link>http://www.xml.com</link>
+ <url>http://xml.com/universal/images/xml_tiny.gif</url>
+ </image>
+
+ <item>
+ <title>XML: A Disruptive Technology</title>
+ <link>http://c.moreover.com/click/here.pl?r123</link>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical
+ infrastructure of the Internet.
+ </dc:description>
+ <dc:publisher>The O'Reilly Network</dc:publisher>
+ <dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>
+ <dc:rights>Copyright &#169; 2000 O'Reilly &amp; Associates, Inc.</dc:rights>
+ <dc:subject>XML</dc:subject>
+ </item>
+
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/feed_items_length_zero.xml b/toolkit/components/feeds/test/xml/rss1/feed_items_length_zero.xml
new file mode 100644
index 000000000..a935b9ad9
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/feed_items_length_zero.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed w/ zero items count
+Expect: feed.items.length == 0
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ </channel>
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/feed_link.xml b/toolkit/components/feeds/test/xml/rss1/feed_link.xml
new file mode 100644
index 000000000..f304a63e8
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/feed_link.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed title works normalized
+Expect: feed.fields.getProperty('rss1:link') == 'http://xml.com/pub'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ </channel>
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/feed_link_normalized.xml b/toolkit/components/feeds/test/xml/rss1/feed_link_normalized.xml
new file mode 100644
index 000000000..ba9674746
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/feed_link_normalized.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed link works normalized
+Expect: feed.link.spec == 'http://xml.com/pub'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ </channel>
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/feed_textInput.xml b/toolkit/components/feeds/test/xml/rss1/feed_textInput.xml
new file mode 100644
index 000000000..ea5639477
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/feed_textInput.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed w/ textinput
+Expect: feed.textInput.getProperty('rdf:about') == 'http://search.xml.com'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ </channel>
+
+ <textinput rdf:about="http://search.xml.com">
+ <title>Search XML.com</title>
+ <description>Search XML.com's XML collection</description>
+ <name>s</name>
+ <link>http://search.xml.com</link>
+ </textinput>
+
+ <item>
+ <title>XML: A Disruptive Technology</title>
+ <link>http://c.moreover.com/click/here.pl?r123</link>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical
+ infrastructure of the Internet.
+ </dc:description>
+ <dc:publisher>The O'Reilly Network</dc:publisher>
+ <dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>
+ <dc:rights>Copyright &#169; 2000 O'Reilly &amp; Associates, Inc.</dc:rights>
+ <dc:subject>XML</dc:subject>
+ </item>
+ <item>
+
+ </item>
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/feed_title.xml b/toolkit/components/feeds/test/xml/rss1/feed_title.xml
new file mode 100644
index 000000000..121545d38
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/feed_title.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed title works
+Expect: feed.fields.getProperty('rss1:title') == 'Test'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ </channel>
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/feed_title_extra_att.xml b/toolkit/components/feeds/test/xml/rss1/feed_title_extra_att.xml
new file mode 100644
index 000000000..b24550696
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/feed_title_extra_att.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed title works
+Expect: feed.fields.getProperty('rss1:title') == 'Test'
+
+-->
+<rdf:RDF
+ xmlns:foo="http://example.org"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title foo:bar="baz">Test</title>
+ </channel>
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/feed_title_normalized.xml b/toolkit/components/feeds/test/xml/rss1/feed_title_normalized.xml
new file mode 100644
index 000000000..5bd6ccefd
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/feed_title_normalized.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed title works normalized
+Expect: feed.title.plainText() == 'Test'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ </channel>
+</rdf:RDF>
diff --git a/toolkit/components/feeds/test/xml/rss1/feed_updated.xml b/toolkit/components/feeds/test/xml/rss1/feed_updated.xml
new file mode 100644
index 000000000..4aed87e98
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/feed_updated.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed updated
+Expect: feed.updated == 'Sat, 07 Sep 2002 00:00:01 GMT'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ <dc:date>Sat, 07 Sep 2002 00:00:01 GMT</dc:date>
+ </channel>
+ <item rdf:about="http://example.com/hmm">
+ <title>XML: A Disruptive Technology</title>
+ <link>http://c.moreover.com/click/here.pl?r123</link>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical
+ infrastructure of the Internet.
+ </dc:description>
+ </item>
+</rdf:RDF>
diff --git a/toolkit/components/feeds/test/xml/rss1/feed_updated_dctermsmodified.xml b/toolkit/components/feeds/test/xml/rss1/feed_updated_dctermsmodified.xml
new file mode 100644
index 000000000..24b9fc92c
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/feed_updated_dctermsmodified.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed updated
+Expect: feed.updated == 'Sat, 07 Sep 2002 00:00:01 GMT'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'
+ xmlns:dcterms='http://purl.org/dc/terms/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ <dcterms:modified>Sat, 07 Sep 2002 00:00:01 GMT</dcterms:modified>
+ </channel>
+ <item rdf:about="http://example.com/hmm">
+ <title>XML: A Disruptive Technology</title>
+ <link>http://c.moreover.com/click/here.pl?r123</link>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical
+ infrastructure of the Internet.
+ </dc:description>
+ </item>
+</rdf:RDF>
diff --git a/toolkit/components/feeds/test/xml/rss1/feed_version.xml b/toolkit/components/feeds/test/xml/rss1/feed_version.xml
new file mode 100644
index 000000000..8147a970c
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/feed_version.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 Version works
+Expect: result.version == 'rss1'
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ </channel>
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/full_feed.xml b/toolkit/components/feeds/test/xml/rss1/full_feed.xml
new file mode 100644
index 000000000..7dae34c85
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/full_feed.xml
@@ -0,0 +1,41 @@
+<!--
+
+Description: atom generator works
+Expect: result.bozo == true && feed.items.length == 1
+
+-->
+<rdf:RDF
+xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+xmlns:dc="http://purl.org/dc/elements/1.1/"
+xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
+xmlns:admin="http://webns.net/mvcb/"
+xmlns:cc="http://web.resource.org/cc/"
+xmlns="http://purl.org/rss/1.0/">
+
+<channel rdf:about="http://example.org/">
+<title>fooo</title>
+<link>http://weblogs.example.org/</link>
+<description>fooooooo</description>
+<dc:language>en-us</dc:language>
+<dc:creator></dc:creator>
+<dc:date>2006-04-10T08:38:18-08:00</dc:date>
+<admin:generatorAgent rdf:resource="http://www.movabletype.org/?v=3.2" />
+
+
+<items>
+<rdf:Seq>
+<rdf:li rdf:resource="http://weblogs.example.org/archives/009698.html" />
+</rdf:Seq>
+
+</items>
+
+</channel>
+<item rdf:about="http://weblogs.example.org/archives/009698.html">
+<title>Come From?</title>
+<link>http://example.org/009698.html</link>
+<description><![CDATA[
+ %G–%@ much of the code
+]]></description>
+<dc:date>2006-02-06T10:19:03-08:00</dc:date>
+</item>
+</rdf:RDF>
diff --git a/toolkit/components/feeds/test/xml/rss1/full_feed_not_bozo.xml b/toolkit/components/feeds/test/xml/rss1/full_feed_not_bozo.xml
new file mode 100644
index 000000000..61ae8a220
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/full_feed_not_bozo.xml
@@ -0,0 +1,354 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: Full RSS1 feed not bozo
+Expect: result.bozo == false
+
+-->
+<rdf:RDF
+xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+xmlns:dc="http://purl.org/dc/elements/1.1/"
+xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
+xmlns:admin="http://webns.net/mvcb/"
+xmlns:cc="http://web.resource.org/cc/"
+xmlns="http://purl.org/rss/1.0/">
+
+<channel rdf:about="http://weblogs.mozillazine.org/ben/">
+<title>Inside Firefox</title>
+<link>http://weblogs.mozillazine.org/ben/</link>
+<description>The Inside Track on Firefox Development</description>
+<dc:language>en-us</dc:language>
+<dc:creator></dc:creator>
+<dc:date>2006-04-26T14:34:49-08:00</dc:date>
+<admin:generatorAgent rdf:resource="http://www.movabletype.org/?v=3.2" />
+
+
+<items>
+<rdf:Seq><rdf:li rdf:resource="http://weblogs.mozillazine.org/ben/archives/010115.html" />
+<rdf:li rdf:resource="http://weblogs.mozillazine.org/ben/archives/010109.html" />
+<rdf:li rdf:resource="http://weblogs.mozillazine.org/ben/archives/010075.html" />
+<rdf:li rdf:resource="http://weblogs.mozillazine.org/ben/archives/010074.html" />
+<rdf:li rdf:resource="http://weblogs.mozillazine.org/ben/archives/010073.html" />
+<rdf:li rdf:resource="http://weblogs.mozillazine.org/ben/archives/010040.html" />
+<rdf:li rdf:resource="http://weblogs.mozillazine.org/ben/archives/010030.html" />
+<rdf:li rdf:resource="http://weblogs.mozillazine.org/ben/archives/010011.html" />
+<rdf:li rdf:resource="http://weblogs.mozillazine.org/ben/archives/009965.html" />
+<rdf:li rdf:resource="http://weblogs.mozillazine.org/ben/archives/009964.html" />
+<rdf:li rdf:resource="http://weblogs.mozillazine.org/ben/archives/009943.html" />
+<rdf:li rdf:resource="http://weblogs.mozillazine.org/ben/archives/009924.html" />
+<rdf:li rdf:resource="http://weblogs.mozillazine.org/ben/archives/009914.html" />
+<rdf:li rdf:resource="http://weblogs.mozillazine.org/ben/archives/009804.html" />
+<rdf:li rdf:resource="http://weblogs.mozillazine.org/ben/archives/009774.html" />
+</rdf:Seq>
+</items>
+
+</channel>
+
+<item rdf:about="http://weblogs.mozillazine.org/ben/archives/010115.html">
+<title>Firefox 2 Is Cool</title>
+<link>http://weblogs.mozillazine.org/ben/archives/010115.html</link>
+<description><![CDATA[<p>A lot of people read my previous post and came to a very reasonable conclusion: "If you take Places out of Firefox 2, shouldn't it be called Firefox 1.6?"</p>
+
+<p>I don't agree that Places was the one and only thing that sold Firefox 2 though. I took a look through the <a href="http://wiki.mozilla.org/Firefox2/Requirements">Firefox 2 Requirements</a> page to look at some of the other stuff that's going on. Reading that document, I think I can see now why people are down in the dumps about no-places Firefox 2. I don't think that document necessarily does the best possible job of capturing the excitement I have about some of the Firefox 2 features we're pursuing. </p>
+
+<p>For the past week or so, I've been toting around a printout of another document, which I wrote because I wanted to convey some of the vision I have of the Firefox 2 product as a whole - a more holistic view as it were. </p>
+
+<h3>Safer, Faster, Better</h3>
+
+<p>If you take a look at the black buttons stacked in the right column of this page, you'll see that one of them reads "Safer, Faster, Better." I don't knowwho came up with that one but it's a good tag line. It has a certain cadence about it. People have attached lots of these to Firefox in the past - "Take Back the Web" was the one I came up with, there's "Rediscover the Web", the FirefoxFlicks project has yielded a few good ones too - I like "<a href="http://www.firefoxflicks.com/flick/index.php?sort=new&id=21122&c=false">Web For All</a>". But "Safer, Faster, Better" is not just a tag line, it can also map into a set of themes for product development. </p>
+
+<p>So, taking a look at the Requirements page, I attempted to do that. My document wasn't a comprehensive collection of everything on that page, I was focused more on the things immediately visible to most users. I guess my problem with the Requirements page has always been its very engineering/technical focus. The result of this is that the priority of items tend to reflect how difficult something is to implement, or where it lies in the development cycle, not necessarily the impact on the user. What I ended up with I guess is a sort of "Shadow PRD" that reflects what I personally thought was cool about Firefox 2, and what I wanted to get out of it. </p>
+
+<p>A copy of the document is <a href="http://www.bengoodger.com/software/mb/2.0/firefox2-vision.html">here</a>. <br />
+Some notes:</p>
+
+<ul>
+ <li>Assume the scratched out section for "Retracing Your Steps" will be part
+ of a future release.
+ <li>The priorities shown are my opinion, and relate to potential impact on
+ the user.
+ <li>The document does not represent all of the work being done, just a
+ readily marketable subset.
+</ul>
+
+<p>All in all, I think there's easily enough here to justify a "2" designation. That's just my opinion though. I also think whole numbers are probably easier for the general populace to understand than decimals. </p>
+
+<p>Firefox has never been about date driven development (within reason). The changes with Places should not be seen as a change in this sentiment. What we're about is high quality software development with real advantages to <br />
+users, and I think that with the updated plan we're still on a trajectory that supports and encourages that, perhaps more firmly now than before.</p>
+
+<p>And that's it from today's "Ben waits for the tinderboxen to clear" report. </p>]]></description>
+<dc:subject></dc:subject>
+<dc:creator>ben</dc:creator>
+<dc:date>2006-04-26T14:34:49-08:00</dc:date>
+</item>
+<item rdf:about="http://weblogs.mozillazine.org/ben/archives/010109.html">
+<title>Firefox 2 Content Update</title>
+<link>http://weblogs.mozillazine.org/ben/archives/010109.html</link>
+<description><![CDATA[<p>When we began work on Firefox 2, we decided to focus on a development branch, a continuation of the Mozilla 1.8 branch. The reason for doing this was that there was to be a lot of significant architectural changes going on on the trunk, with the prospect of a new rendering back end, a rearchitecture of reflow in layout, and various other things. Shipping a Firefox 2 release in 2006 off of this code did not seem possible. </p>
+
+<p>As a result, we decided to pursue a release focused on application level improvements, on a separate branch. Going into it, we knew the perils of multi-branch development. We knew the divergences that would inevitably form between branch and trunk. We had experience from the painful development of Firefox 1.0 on the Aviary branch. We resolved to be more methodical about our commits, but we knew to expect some pain. The goal was to produce a high value release in short enough time so that we could all return to the trunk and help build new features that utilize the back end being developed there, to help shake them out. </p>
+
+<p>Late last year, we put together a list of things to pursue for the Firefox 2 release. A month or so ago, we got together as a group and formalized this more in a <a href="http://wiki.mozilla.org/Firefox2/Requirements">Firefox 2 PRD</a>. We had scheduled four major pre-release milestones, two alphas and two betas. We have already shipped one alpha. The intent of the second is to be "Feature Complete".</p>
+
+<p>The people driving the various sub-projects on the Requirements list get together weekly to check status. As the weeks have gone by, it has become clear to us that the most complex feature on the plan is Places. It is easily an order of magnitude more complex than anything else on the plan. Places is a great feature and it has been exciting watching its capabilities grow. We are looking forward to the capabilities that it will expose. What we have learned though is that the work required to complete Places is probably too substantial to gate the Firefox 2 release. It falls more into the "significant rearchitecture" category of feature that's generally been targeted at Firefox 3.</p>
+
+<p>What we have decided to do is as follows:</p>
+
+<ul>
+<li>We will disable places on the 1.8 branch, reverting the user interface and back end to Firefox 1.x functionality.
+<li>We will continue to aggressively develop the capabilities of Places on the 1.9 trunk. Places will remain enabled here.
+</ul>
+
+<p>We think this is a good decision for two reasons:</p>
+
+<ul>
+<li>It reduces the pressure on the Places team to deliver a lot of bug fixes and additional features on the very immediate timeframe required by the Firefox 2 testing releases. It is my opinion that doing so would impact the quality of the feature, if we did not add at least a couple more alpha cycles to the process. This decision provides us with an opportunity to really make the architecture and user interface of Places reach their full potential.
+<li>It allows us as a group to circle around and consider the content of the Firefox 2 release holistically, identify high impact at risk areas and spend some more time on them. One of those for me was Feed Handling.
+</ul>
+
+<p>Michael Schroepfer of the Mozilla Corporation has a <a href="http://groups.google.com/group/mozilla.dev.planning/browse_frm/thread/4b8e7bafecccbc10/8997efd5d5d5f03f">newsgroup posting</a> with additional information. His thread is also the most appropriate forum for discussion of this topic. </p>
+
+<p>I have been working on refining some of the messaging surrounding feature content and prioritization on the PRD. I will post the initial results of that here soon.</p>]]></description>
+<dc:subject></dc:subject>
+<dc:creator>ben</dc:creator>
+<dc:date>2006-04-24T09:30:54-08:00</dc:date>
+</item>
+<item rdf:about="http://weblogs.mozillazine.org/ben/archives/010075.html">
+<title>Did I Mention...</title>
+<link>http://weblogs.mozillazine.org/ben/archives/010075.html</link>
+<description><![CDATA[<p>... that I hate this computer?</p>
+
+<p>While I'm at it... the up arrow key cap fell off after about three weeks, in early 2004. About six months later I lost the little rubber membrane thing that made it slightly easier to push the arrow. Since then, I've been typing by pushing down on the little connection thingy on the keyboard tray. </p>
+
+<p>It's been shedding pieces of plastic too. I've never dropped the computer once, but pieces of the shell have begun to snap off. </p>
+
+<p>When I first got it, when the secondary battery was in place, when the primary drained the machine would hibernate, even though the secondary was present! Pretty awful bug to ship with. There was never a solution that I could find. Speaking of batteries, the primary battery is pretty much toast... it won't go for more than 5 minutes before shutting down. It began doing this at around the 12-18 month mark. And the battery light permanently flashes orange whenever the system is on. </p>
+
+<p>Why don't I call the hotline? I guess I'll have to, before my warranty runs out. I don't because it usually involves 45 minutes on hold or explaining to someone who only has a script to read from that the issue involving a missing up arrow doesn't require restarting Windows or running some stupid diagnostic tool. I could have paid more for "premium support" at build-time but I found that concept sort of insulting: why should I have to pay extra to speak to someone who is smart and doesn't think I'm a moron?</p>
+
+<p>And I don't want a Thinkpad either. I hate those computers. They have old-fashioned 4:3 displays, and the function key and left Ctrl key are reversed. I know I could map them differently but why would I? Why couldn't IBM just have designed the product correctly in the first place? Oh, and I'd sooner drink paint than run the awful IBM access connections software to connect to a wireless network, or deal with the fact that the Num Lock key seems to reset to ON every time the system is rebooted.</p>
+
+<p>Why doesn't someone make the perfect laptop? I'd be interested to hear from someone how long the compile times are for FirefoxDebug on a 2.16GHz MacBook Pro...</p>]]></description>
+<dc:subject></dc:subject>
+<dc:creator>ben</dc:creator>
+<dc:date>2006-04-16T19:11:28-08:00</dc:date>
+</item>
+<item rdf:about="http://weblogs.mozillazine.org/ben/archives/010074.html">
+<title>I Hate This Computer</title>
+<link>http://weblogs.mozillazine.org/ben/archives/010074.html</link>
+<description><![CDATA[<p>I have been fighting with this computer for the past few days to do a build with a few patches applied. </p>
+
+<p>First, I managed to get a certain distance with a branch build, compiling with Visual C++ 6.0. But soon I realized there were too many dependencies that were trunk specific, so I had to build trunk. About a quarter of the way through my build died, of course, compiling from the same shell, wrong version of VC6.0 for Cairo/Thebes. </p>
+
+<p>Starting over again with the VC7 tools, another failure towards the end. Some sort of cyclic dependency check error. Clobber and restart. Now I forgot one of my patches had a configure change, and the process begins anew, I have effectively clobbered. </p>
+
+<p><a href="http://weblogs.mozillazine.org/ben/archives/2003_12.html">When I bought this machine</a>, a Dell Precision M60 with a Pentium M 1.7GHz processor, a 7200rpm disk and a gig of RAM, it could compile Firefox start to stop in 21 minutes. Now it takes over an hour.</p>
+
+<p>The situation is better on my Google-supplied workstation, but for how long? Over time, Windows reaches a point of being completely useless for anything aside from the most basic activities. What's the effect? I had planned to work both days this weekend on Firefox 2 features. Instead I spent the whole time fighting one of the most frustrating fights possible, and have achieved nothing. I hate Windows. I hate this computer.</p>]]></description>
+<dc:subject></dc:subject>
+<dc:creator>ben</dc:creator>
+<dc:date>2006-04-16T18:58:02-08:00</dc:date>
+</item>
+<item rdf:about="http://weblogs.mozillazine.org/ben/archives/010073.html">
+<title>Miscommunications</title>
+<link>http://weblogs.mozillazine.org/ben/archives/010073.html</link>
+<description><![CDATA[<p>My laptop was running pretty slowly yesterday so I decided to scan the Add/Remove Programs list to clear out the cruft. Things were really chugging along. I sequentially uninstalled several pieces of software, and the process was very dissatisfying. I became more and more enfuriated at my computer as it proceeded. Here are some of the nuisances:</p>
+
+<ul>
+<li>I could only remove one thing at a time.
+<li>Many pieces of software used the Windows Installer system which seemed to take forever and report very inconsistent progress (I know, Firefox isn't the best at this in its installer, either)
+<li>Most annoyingly, the uninstaller apps all reported themselves as performing a variety of actions that I never requested, as explanations for what they were doing during long periods of inactivity and progress-bar freeze. Common excuses were "Windows is Configuring <blah>" and "InstallShield is preparing a report on <bleh>".
+</ul>
+
+<p>You know, I never <strong>asked</strong> for blah to be "configured." I never asked for a report on bleh (What am I, a manager? Where is the report anyway? Does it have the appropriate cover sheet?) <strong>I just want the software gone</strong>. I'm getting really tired of excuses from software like this. Windows software seems to be getting worse and worse. On Mac, the typical way to remove a program is to drag it into the trash can. I can even do that to several programs at once! I do however have to be able to afford a Mac (I can, I have one). Many folk aren't as fortunate as I. </p>
+
+<p>As a side note, I read an interesting article in Forbes a few weeks ago criticizing Microsoft for its delays shipping Vista, and asking why wouldn't you just side-step all the trouble and buy a Mac, since the odds were good many people would have to upgrade their PC anyway just to get the whiz-bang in Vista. The article side-swiped open source desktop initiatives, asking where the viable free alternative was. I think that was an interesting point, and especially so since the capabilities of Linux systems have come an awesome distance in the past few years but there have been few distributions or desktop environments that IMO make the most of all of those.</p>]]></description>
+<dc:subject></dc:subject>
+<dc:creator>ben</dc:creator>
+<dc:date>2006-04-16T18:05:04-08:00</dc:date>
+</item>
+<item rdf:about="http://weblogs.mozillazine.org/ben/archives/010040.html">
+<title>Firefox Version Numbers</title>
+<link>http://weblogs.mozillazine.org/ben/archives/010040.html</link>
+<description><![CDATA[<p>Mike Beltzner <a href="http://www.beltzner.ca/mike/archives/2006/04/10/when_3_is_less_than_2.html">explains</a> Firefox version numbering. i.e. Firefox 3 RTM is not "out".</p>]]></description>
+<dc:subject></dc:subject>
+<dc:creator>ben</dc:creator>
+<dc:date>2006-04-10T08:38:18-08:00</dc:date>
+</item>
+<item rdf:about="http://weblogs.mozillazine.org/ben/archives/010030.html">
+<title>Our Next Challenge?</title>
+<link>http://weblogs.mozillazine.org/ben/archives/010030.html</link>
+<description><![CDATA[<p>The past year or so has been interesting. In this time, I've been able to meet a lot of new people and learn a lot of new things. Most importantly is that for the first time in as long as I can remember, I have had a chance to see the Mozilla project from the outside, as it would appear to someone who was trying to build on Mozilla technology or contribute directly to a project, but was not part of Netscape "back in the day" or an employee of the Mozilla Foundation/Corporation itself. </p>
+
+<p>It's been an illuminating experience. From a technical perspective, it helped highlight APIs that I had developed without a clear understanding of how they would be used. The Extension Installation API was one example of this, and we were able to make some great improvements to it in 2005.</p>
+
+<p>But perhaps more importantly it has shed some light on how people perceive Mozilla as an open source project. These perceptions are not the sort of things people express explicitly. You have to notice them.</p>
+
+<h3>The Difficulty of Involvement</h3>
+
+<p>This is sort of the uber-perception. I think some of the reasons for this include the following:</p>
+
+<h3>Where is the Discussion?</h3>
+
+<p>Which newsgroup/mailing list/IRC channel/wiki/talk page/bug/forum page do I need to track in order to know what's going on in a specific area? The answer is unsatisfactorily complex.</p>
+
+<p>The traditional method of joining a project in the OSS world (where you join lists and IRC channels and lurk for a while, gradually ramping up your contributions) scales uneasily to a project the size of Mozilla. The amount of data a mere mortal would have to absorb in order to be productive quickly is staggering. I have in the past jocularly referred to it as the "learning wall". I wonder how many people just give up. </p>
+
+<h3>Madness to Method?</h3>
+
+<p>As a large project, Mozilla has thousands of source files across hundreds of directories. One of my coworkers here at Google commented that he tried to find something as simple as the browser window code a couple of years ago and couldn't, because it lived under the thoughtfully named "xpfe". </p>
+
+<p>There's not a huge amount of documentation - and I'm not just talking about public API docs. I'm talking about the much needed diagrams that show how the various building blocks fit together, and in-code documentation for pretty much anything that isn't intuitive (which is a lot). I've written as little of this as anyone else.</p>
+
+<h3>Tone</h3>
+
+<p>In the past, I have not done the best I could to establish a tone for discourse that is conducive to productive development. My tendency was to snap when provoked. I made two mistakes of judgement here, one was ignoring the effect that this sort of thing would have on those watching, aside from the victim. The other was to think that regardless of the tone set by my actions, we as a group could work through any negative effects. Any work we relied on others for we could do ourselves. Or we could hire through it.</p>
+
+<h3>The Joy of Code</h3>
+
+<p>The flaw with this is that when your project's contributions come solely from companies, for better or for worse the activities of those paid contributors will align in some way with the interests of those companies. What this does not always allow for is the pursuit of the sort of improvements that are outside the scope of these interests. Such things often include raising general code quality, speculative feature development, feature polish and detail etc. I don't mean to say that companies are <em>against</em> these things, but they're often not the primary concern during a release crunch. And what companies like to have is shipping software. </p>
+
+<p>Alternately, even in the absence of corporate support, if there is not enough redundancy that the same set of folk has to do the grunt work over and over, the risk of burnout is high.</p>
+
+<p>I feel this because I have been incredibly "plan" focused over the past few years, formally during my time at Netscape and less formally but no less importantly during the run up to Firefox 1.0 and 1.5. What I notice is that I no longer have time to work on the sort of interesting side projects that I used to enjoy doing when I was first starting out. </p>
+
+<p>For example, about six years ago I discovered a bug in the Bookmarks menu shortly after scrolling was implemented. When you moused into a submenu for a folder that was in the scrolled section, the sub menu popup was pushed off the bottom of the screen. I took a couple of days to learn the menu positioning code and fix the math error that was causing the bug. The exercise was good for me in a number of ways: I learned more about another section of the code, my general expertise was raised, and well.. I fixed the bug that was bothering<br />
+me.</p>
+
+<p>I think we need to have a project that is accessible to volunteers for this reason. We also need to provide a way to allow those volunteers to grow if they want to, so that if you're one of the folk at the center you can have a chance to step aside for a moment and take a breather and code for the pure joy of it. </p>
+
+<p>Full time paid contributors will always be a part of Open Source development. But I don't think release-focused agendas will ever be a substitute for the passion of folk who participate because of the joy of exploration and of contribution. </p>
+
+<h3>Looking Outward, Looking Forward</h3>
+
+<p>As a project, we have made overtures towards being a more inclusive lot. For some of the reasons I've listed here, I think as a project we're still more inward looking than outward. How many of us have thought about what we want to be doing in 5 years? Will we always be doing this? Will our roles remain the same? My opinion is that it's fast becoming time for us to start considering making personal sacrifices in our short term conveniences to make the project more accessible to new people. Do I know what we need to do? Not exactly. But I have some ideas: find ways to make our discussions, our public faces, and our code more accessible.</p>
+
+<p>With Firefox we did an excellent job of building a world class product that people wanted to use. We have a new challenge now, one that is larger and scope and in the long run in my opinion considerably more important because the long term success of products like Firefox depend on it. How will we grow a world class development community? How will we ensure that the freedoms we enjoy are protected, forever?</p>]]></description>
+<dc:subject></dc:subject>
+<dc:creator>ben</dc:creator>
+<dc:date>2006-04-07T09:22:59-08:00</dc:date>
+</item>
+<item rdf:about="http://weblogs.mozillazine.org/ben/archives/010011.html">
+<title>Congrats Relicensing Project!</title>
+<link>http://weblogs.mozillazine.org/ben/archives/010011.html</link>
+<description><![CDATA[<p><a href="http://weblogs.mozillazine.org/gerv/archives/2006/03/relicensing_complete.html">Gerv announces</a> that the Relicensing project is complete. Congrats Gerv and everyone else who doggedly pursued this over the years. Part of Mozilla's mission is preserving choice, and making our code available under a variety of flexible licenses helps ensure that by allowing other projects to make use of it. This was a formidable task and a great accomplishment. </p>]]></description>
+<dc:subject></dc:subject>
+<dc:creator>ben</dc:creator>
+<dc:date>2006-04-04T07:15:22-08:00</dc:date>
+</item>
+<item rdf:about="http://weblogs.mozillazine.org/ben/archives/009965.html">
+<title>Producing Open Source Software</title>
+<link>http://weblogs.mozillazine.org/ben/archives/009965.html</link>
+<description><![CDATA[<p>I've been reading Karl Fogel's excellent <a href="http://www.producingoss.com/">Producing Open Source Software</a>. </p>
+
+<p>Karl's book is very well written, nice and compact (272 pages), and contains useful information for anyone doing anything in the Open Source world: both developers and managers. </p>
+
+<p>It will help people new to Open Source get a better understanding of how OSS projects are run. It will help people familiar with Open Source to get a better understanding of how to contribute more effectively.</p>
+
+<p>It's definitely a "must read."</p>]]></description>
+<dc:subject></dc:subject>
+<dc:creator>ben</dc:creator>
+<dc:date>2006-03-26T15:03:52-08:00</dc:date>
+</item>
+<item rdf:about="http://weblogs.mozillazine.org/ben/archives/009964.html">
+<title>Writing for Busy People</title>
+<link>http://weblogs.mozillazine.org/ben/archives/009964.html</link>
+<description><![CDATA[<p>Back when I was in <a href="http://www2.ece.auckland.ac.nz/">University</a>, many of the lecturers stressed time and time again the importance of succinct, well organized writing. They said over and over that this was the best way to have your thoughts read and understood by decision makers. In fact, they scared us by saying that 70% of us would become managers sooner or later!</p>
+
+<p>Well, I can tell you that's sage advice. It's great when people make contributions in the form of ideas and proposals, but it's even better when they're written for busy people. Here are some examples:</p>
+
+<ul>
+ <li>Making important points up front
+ <li>Clear taxonomy of headings, and lots of them
+ <li>Writing clearly and succinctly
+ <li>No long, unbroken paragraphs or tracts of text.
+ <li>Preferring bulleted lists with clear points to paragraphs.
+ <li>Use of emphasis in formatting to make important things clear
+</ul>
+
+<p>These days, I find I don't have a lot of time to read everything carefully, so the better structured a document is, the more I get out of it. I frequently find I miss entire subsections or points of documents, even when there's relatively little text, because of incomplete organization. My eyes definitely glaze over when i see a large block of unbroken text with few headings. At the very least, it'd be very helpful if folk would structure their thoughts into: "Problem" and "Proposed Solution". </p>
+
+<p>Before you post, stop and think if you've written something in a way that'll allow others to get the most out of it. Communicating your ideas effectively means you may get a clearer and quicker response from other people. </p>]]></description>
+<dc:subject>Editorial</dc:subject>
+<dc:creator>ben</dc:creator>
+<dc:date>2006-03-26T14:48:04-08:00</dc:date>
+</item>
+<item rdf:about="http://weblogs.mozillazine.org/ben/archives/009943.html">
+<title>Step 2: Ask Questions</title>
+<link>http://weblogs.mozillazine.org/ben/archives/009943.html</link>
+<description><![CDATA[<p>A healthy project is one where active contributors are always evaluating the project's progress, making sure it is headed in the right direction (usually stated in the project mission or goals). </p>
+
+<p>I think we could be better at this in Mozilla. I'm not suggesting people be assholes or anything, but I think some more pan-project analysis would be useful. </p>
+
+<p>Historically, I can point at a couple of groups of people who have attempted to do something like this. The <code>drivers@</code> group is one that looked beyond individual modules within Gecko to make sure that the right thing for the shipping products as a whole happened. The Firefox team is another example. By taking a holistic view, user experience was enhanced. </p>
+
+<p>I think contributors should not be afraid to poke their nose in other parts of the project and see how things are going. Ask questions. Learn more. Get involved in governance and management. If things don't seem intuitive, or a little arbitrary, ask, rather than assume it's for a good reason. One of the benefits of having an open, referencable set of discussion forums means that once you've answered a question once on the public forums, when someone else asks you can just give them a URL. </p>]]></description>
+<dc:subject></dc:subject>
+<dc:creator>ben</dc:creator>
+<dc:date>2006-03-22T17:27:14-08:00</dc:date>
+</item>
+<item rdf:about="http://weblogs.mozillazine.org/ben/archives/009924.html">
+<title>Step 1: Public Discussions</title>
+<link>http://weblogs.mozillazine.org/ben/archives/009924.html</link>
+<description><![CDATA[<p>The first step on the pathway to open source project happiness is to have our discussions in the public. </p>
+
+<p>One of the things people have (rightly) criticized about Firefox and Mozilla development in the past is that too much happens mysteriously, behind closed doors. This was for a number of reasons that sounded sufficient at the time - it was expedient, people were sitting within shouting distance, mental laziness, etc. </p>
+
+<p>What poor communication breeds is a lack of understanding of procedures, priorities and such like. A healthy project is one where the contributors understanding where things are headed, and what parts they can play. It is one where newcomers can visit the project website and within the space of a few minutes get a decent understanding of how things work, and find out opportunities for them to participate. </p>
+
+<p>People don't want to contribute to projects where things happen "magically". I've learned this lesson in the past. </p>
+
+<p>To this end, I've been encouraging everyone to have public discussions on the <a href="https://lists.mozilla.org/listinfo">Mozilla Newsgroups/Mailing Lists</a>. For Firefox, the list is dev-apps-firefox@, and the newsgroup is mozilla.dev.apps.firefox. They are mirrored through <a href="http://groups.google.com/group/mozilla.dev.apps.firefox">Google Groups</a> for ease of browsing. We're planning on improving the theme for Firefox2, and rather than pursue this effort in a walled garden like last time, we're going to proceed in dev-themes@/mozilla.dev.themes. Come on over and join in!</p>
+
+<p>At the same time, we've been encouraging other projects to use the newsgroups/lists too. Decisions made in private email, IRC (which isn't archived anywhere) even in public bugs etc make it very difficult for people who aren't central to the project to find out more or participate. I think we should strive to strike a better balance between convenience and accessibility/referencability. </p>
+
+<p>On top of this, there is a need to make the contact portions of the web site more accurate, relevant and easy to find, so people can easily find the list they want, and the person or group to contact. </p>
+
+<p>We've been having discussions about all of this in <a href="http://groups.google.com/group/mozilla.dev.general">mozilla.dev.general</a>, in <a href="http://groups.google.com/group/mozilla.dev.general/browse_thread/thread/899917f713861f06/4ae6d094ffee5ae7">these</a> <a href="http://groups.google.com/group/mozilla.dev.general/browse_thread/thread/5d1bf2bbc769919d/210246003f1f6fea">threads</a>. Rather than talk in a vacuum of only ourselves, I really hope that those of you that have experienced difficulty in the past in some of these areas will come forward and contribute to the discussion. </p>]]></description>
+<dc:subject></dc:subject>
+<dc:creator>ben</dc:creator>
+<dc:date>2006-03-20T09:23:24-08:00</dc:date>
+</item>
+<item rdf:about="http://weblogs.mozillazine.org/ben/archives/009914.html">
+<title>Reflection</title>
+<link>http://weblogs.mozillazine.org/ben/archives/009914.html</link>
+<description><![CDATA[<p>I've been doing a bit of it lately. All manner of topics. We recently moved and things have been chaotic so it's been nice to take the time to think. I've had a chance to look at how far we've come, and form some ideas about what we might need to do to go the right places. </p>
+
+<p>The past couple of years have brought some immense highs, and some considerable angst. With success has come the realization that true now as ever: the spirit of open source is expressed through the creative freedom of the many. The surest way to navigate the murky waters of increased attention and marketshare and such like is, as Leslie has been saying for some time, to keep your karma clean. Do the right thing, not only in technical matters but also relationships. </p>
+
+<p>For the Mozilla project, what we need to do (I think) is:</p>
+
+<ul>
+ <li>Better define the things that are important to us. The things that define who we are. Impart the positive aspects of open development culture and practice on everyone involved because they're effective, and as a safeguard against recurrence of some of the <a href="http://weblogs.mozillazine.org/ben/archives/009698.html">troubles of the past</a>.
+ <li>Engage the community more effectively. Create and maintain an infrastructure of open communication to remove the "mystery" behind the decision making process. Organize our contributor materials better to make the project more accessible to newcomers. These are just a couple of examples.
+</ul>
+
+<p>For my part, I'm starting out this year by doing things <a href="http://www.producingoss.com/">a little differently</a>. I think we need to grow more as a project. I'm hopeful that I'll be able to achieve some positive change. </p>
+
+<p>I understand that this post might seem a little abstract. I think what I'm saying might become a bit more clear after I talk about some tangible efforts, which I will do in future entries.</p>]]></description>
+<dc:subject></dc:subject>
+<dc:creator>ben</dc:creator>
+<dc:date>2006-03-19T02:00:07-08:00</dc:date>
+</item>
+<item rdf:about="http://weblogs.mozillazine.org/ben/archives/009804.html">
+<title>Bye Bye Blackberry?</title>
+<link>http://weblogs.mozillazine.org/ben/archives/009804.html</link>
+<description><![CDATA[<p><a href="http://news.com.com/Bye-bye%2C+BlackBerry+-+page+2/2100-1047_3-6042308-2.html?tag=st.num">Bye Bye, Blackberry?</a></p>
+
+<p>I cannot believe people are discussing life without these things. It's like this: I have a patent on television. I don't plan on doing anything with it, but I'm going to shut TV down for all of you, and you're going to sit about and think about life without TV? What's wrong with people?! Is this the world we all want to live in, where people without the interest or capability to pursue technology can hold everyone else captive? That's not the world I want to live in. <br />
+</p>]]></description>
+<dc:subject></dc:subject>
+<dc:creator>ben</dc:creator>
+<dc:date>2006-02-24T10:57:32-08:00</dc:date>
+</item>
+<item rdf:about="http://weblogs.mozillazine.org/ben/archives/009774.html">
+<title>More on Memory</title>
+<link>http://weblogs.mozillazine.org/ben/archives/009774.html</link>
+<description><![CDATA[<p>Firefox's caching behavior is just one area of memory usage. I'm really glad that there's been such a lot of discussion in the previous post I made, since many people have raised specific issues, bugs have been filed, and people are looking at the things people are reporting. This sort of feedback system is one of the things that makes the open development model great. Firefox 2 will be much better because of your help!</p>]]></description>
+<dc:subject></dc:subject>
+<dc:creator>ben</dc:creator>
+<dc:date>2006-02-17T23:44:03-08:00</dc:date>
+</item>
+
+
+</rdf:RDF>
diff --git a/toolkit/components/feeds/test/xml/rss1/full_feed_unknown_extension.xml b/toolkit/components/feeds/test/xml/rss1/full_feed_unknown_extension.xml
new file mode 100644
index 000000000..c2c875b14
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/full_feed_unknown_extension.xml
@@ -0,0 +1,55 @@
+<!--
+
+Description: rss1 unknown elements does not cause error
+Expect: feed.items.length == 1
+
+-->
+<rdf:RDF
+xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+xmlns:dc="http://purl.org/dc/elements/1.1/"
+xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
+xmlns:admin="http://webns.net/mvcb/"
+xmlns:cc="http://web.resource.org/cc/"
+xmlns="http://purl.org/rss/1.0/">
+
+<channel rdf:about="http://example.org/">
+<title>fooo</title>
+<link>http://weblogs.example.org/</link>
+<description>fooooooo</description>
+<dc:language>en-us</dc:language>
+<dc:creator></dc:creator>
+<dc:date>2006-04-10T08:38:18-08:00</dc:date>
+<admin:generatorAgent rdf:resource="http://www.movabletype.org/?v=3.2" />
+
+
+
+
+
+
+
+<foo:bar xmlns:foo="http://example.org">baz</foo:bar>
+
+
+
+
+
+
+
+
+
+
+<items>
+<rdf:Seq>
+<rdf:li rdf:resource="http://weblogs.example.org/archives/009698.html" />
+</rdf:Seq>
+
+</items>
+
+</channel>
+<item rdf:about="http://weblogs.example.org/archives/009698.html">
+<title>Come From?</title>
+<link>http://example.org/009698.html</link>
+<description><![CDATA[much of the code]]></description>
+<dc:date>2006-02-06T10:19:03-08:00</dc:date>
+</item>
+</rdf:RDF>
diff --git a/toolkit/components/feeds/test/xml/rss1/item_2_dc_description.xml b/toolkit/components/feeds/test/xml/rss1/item_2_dc_description.xml
new file mode 100644
index 000000000..03a4bb548
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/item_2_dc_description.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed w/ item 2 dc:description
+Expect: feed.items.queryElementAt(1, Components.interfaces.nsIFeedEntry).fields.getProperty('dc:description') == 'XML is placing increasingly heavy loads on the existing technical infrastructure of the Internet 2.'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ </channel>
+ <item>
+ <title>XML: A Disruptive Technology</title>
+ <link>http://c.moreover.com/click/here.pl?r123</link>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical infrastructure of the Internet.
+ </dc:description>
+ <!-- <dc:publisher>The O'Reilly Network</dc:publisher>
+ <dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>
+ <dc:rights>Copyright &#169; 2000 O'Reilly &amp; Associates, Inc.</dc:rights>
+ <dc:subject>XML</dc:subject>-->
+ </item>
+ <item>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical infrastructure of the Internet 2.
+ </dc:description>
+ <title>XML: A Disruptive Technology</title>
+ </item>
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/item_2_dc_publisher.xml b/toolkit/components/feeds/test/xml/rss1/item_2_dc_publisher.xml
new file mode 100644
index 000000000..d21734d6f
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/item_2_dc_publisher.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed w/ item 2 dc:publisher
+Expect: feed.items.queryElementAt(1, Components.interfaces.nsIFeedEntry).fields.getProperty('dc:publisher') == 'The O\'Reilly Network'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ </channel>
+ <item>
+ <title>XML: A Disruptive Technology</title>
+ <link>http://c.moreover.com/click/here.pl?r123</link>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical infrastructure of the Internet.
+ </dc:description>
+ <!--
+ <dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>
+ <dc:rights>Copyright &#169; 2000 O'Reilly &amp; Associates, Inc.</dc:rights>
+ <dc:subject>XML</dc:subject>-->
+ </item>
+ <item>
+ <dc:publisher>The O'Reilly Network</dc:publisher>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical infrastructure of the Internet 2.
+ </dc:description>
+ <title>XML: A Disruptive Technology</title>
+ </item>
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/item_2_dc_publisher_extra_att_invalid_rdf.xml b/toolkit/components/feeds/test/xml/rss1/item_2_dc_publisher_extra_att_invalid_rdf.xml
new file mode 100644
index 000000000..dac0d1dc8
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/item_2_dc_publisher_extra_att_invalid_rdf.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed w/ item 2 dc:publisher
+Expect: feed.items.queryElementAt(1, Components.interfaces.nsIFeedEntry).fields.getProperty('dc:publisher') == 'The O\'Reilly Network'
+
+-->
+<rdf:RDF
+ xmlns:foo="http://example.org"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ </channel>
+ <item>
+ <title>XML: A Disruptive Technology</title>
+ <link>http://c.moreover.com/click/here.pl?r123</link>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical infrastructure of the Internet.
+ </dc:description>
+ <!--
+ <dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>
+ <dc:rights>Copyright &#169; 2000 O'Reilly &amp; Associates, Inc.</dc:rights>
+ <dc:subject>XML</dc:subject>-->
+ </item>
+ <item>
+ <dc:publisher foo:bar="baz">The O'Reilly Network</dc:publisher>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical infrastructure of the Internet 2.
+ </dc:description>
+ <title>XML: A Disruptive Technology</title>
+ </item>
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/item_count.xml b/toolkit/components/feeds/test/xml/rss1/item_count.xml
new file mode 100644
index 000000000..69520fb14
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/item_count.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed w/ 1 item count
+Expect: feed.items.length == 2
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ </channel>
+ <item>
+ <!-- <title>XML: A Disruptive Technology</title>
+ <link>http://c.moreover.com/click/here.pl?r123</link>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical
+ infrastructure of the Internet.
+ </dc:description>
+ <dc:publisher>The O'Reilly Network</dc:publisher>
+ <dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>
+ <dc:rights>Copyright &#169; 2000 O'Reilly &amp; Associates, Inc.</dc:rights>
+ <dc:subject>XML</dc:subject>-->
+ </item>
+ <item>
+
+ </item>
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/item_dc_creator.xml b/toolkit/components/feeds/test/xml/rss1/item_dc_creator.xml
new file mode 100644
index 000000000..71ecd6d77
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/item_dc_creator.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed w/ item dc:description
+Expect: var author = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).authors.queryElementAt(0, Components.interfaces.nsIFeedPerson); (author.name == "Simon St.Laurent" && author.email == "simonstl@simonstl.com")
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ </channel>
+ <item>
+ <title>XML: A Disruptive Technology</title>
+ <link>http://c.moreover.com/click/here.pl?r123</link>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical infrastructure of the Internet.
+ </dc:description>
+ <dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>
+ <dc:rights>Copyright &#169; 2000 O'Reilly &amp; Associates, Inc.</dc:rights>
+ <dc:subject>XML</dc:subject>
+ </item>
+ <item>
+ <dc:publisher>The O'Reilly Network</dc:publisher>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical infrastructure of the Internet 2.
+ </dc:description>
+ <title>XML: A Disruptive Technology</title>
+ </item>
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/item_dc_description.xml b/toolkit/components/feeds/test/xml/rss1/item_dc_description.xml
new file mode 100644
index 000000000..3d7880e8c
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/item_dc_description.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed w/ item dc:description
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).fields.getProperty('dc:description') == 'XML is placing increasingly heavy loads on the existing technical infrastructure of the Internet.'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ </channel>
+ <item>
+ <title>XML: A Disruptive Technology</title>
+ <link>http://c.moreover.com/click/here.pl?r123</link>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical infrastructure of the Internet.
+ </dc:description>
+ <!--
+ <dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>
+ <dc:rights>Copyright &#169; 2000 O'Reilly &amp; Associates, Inc.</dc:rights>
+ <dc:subject>XML</dc:subject>-->
+ </item>
+ <item>
+ <dc:publisher>The O'Reilly Network</dc:publisher>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical infrastructure of the Internet 2.
+ </dc:description>
+ <title>XML: A Disruptive Technology</title>
+ </item>
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/item_dc_description_normalized.xml b/toolkit/components/feeds/test/xml/rss1/item_dc_description_normalized.xml
new file mode 100644
index 000000000..d57477a99
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/item_dc_description_normalized.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed w/ item dc:description
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).summary.plainText() == 'XML is...'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ </channel>
+ <item>
+ <dc:description>XML is...</dc:description>
+ <title>XML: A Disruptive Technology</title>
+ <link>http://c.moreover.com/click/here.pl?r123</link>
+ <description>
+ XML is placing increasingly heavy loads on the existing technical infrastructure of the Internet.
+ </description>
+
+ <!--
+ <dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>
+ <dc:rights>Copyright &#169; 2000 O'Reilly &amp; Associates, Inc.</dc:rights>
+ <dc:subject>XML</dc:subject>-->
+ </item>
+ <item>
+ <dc:publisher>The O'Reilly Network</dc:publisher>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical infrastructure of the Internet 2.
+ </dc:description>
+ <title>XML: A Disruptive Technology</title>
+ </item>
+</rdf:RDF>
diff --git a/toolkit/components/feeds/test/xml/rss1/item_description.xml b/toolkit/components/feeds/test/xml/rss1/item_description.xml
new file mode 100644
index 000000000..db4a0137f
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/item_description.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed w/ item desc normalized
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).summary.plainText() == 'XML is placing increasingly heavy loads on the existing technical infrastructure of the Internet.'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ </channel>
+ <item>
+ <title>XML: A Disruptive Technology</title>
+ <link>http://c.moreover.com/click/here.pl?r123</link>
+ <description>
+ XML is placing increasingly heavy loads on the existing technical infrastructure of the Internet.
+ </description>
+ <!-- <dc:publisher>The O'Reilly Network</dc:publisher>
+ <dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>
+ <dc:rights>Copyright &#169; 2000 O'Reilly &amp; Associates, Inc.</dc:rights>
+ <dc:subject>XML</dc:subject>-->
+ </item>
+ <item>
+
+ </item>
+</rdf:RDF>
diff --git a/toolkit/components/feeds/test/xml/rss1/item_id.xml b/toolkit/components/feeds/test/xml/rss1/item_id.xml
new file mode 100644
index 000000000..50048b0a3
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/item_id.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed w/ item rdf:about
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).id == 'http://example.com/hmm'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ </channel>
+ <item rdf:about="http://example.com/hmm">
+ <title>XML: A Disruptive Technology</title>
+ <link>http://c.moreover.com/click/here.pl?r123</link>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical
+ infrastructure of the Internet.
+ </dc:description>
+ <!-- <dc:publisher>The O'Reilly Network</dc:publisher>
+ <dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>
+ <dc:rights>Copyright &#169; 2000 O'Reilly &amp; Associates, Inc.</dc:rights>
+ <dc:subject>XML</dc:subject>-->
+ </item>
+ <item>
+
+ </item>
+</rdf:RDF>
diff --git a/toolkit/components/feeds/test/xml/rss1/item_link.xml b/toolkit/components/feeds/test/xml/rss1/item_link.xml
new file mode 100644
index 000000000..8ead15fb6
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/item_link.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed w/ item link
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).fields.getProperty('rss1:link') == 'http://c.moreover.com/click/here.pl?r123'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ </channel>
+ <item>
+ <title>XML: A Disruptive Technology</title>
+ <link>http://c.moreover.com/click/here.pl?r123</link>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical
+ infrastructure of the Internet.
+ </dc:description>
+ <!-- <dc:publisher>The O'Reilly Network</dc:publisher>
+ <dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>
+ <dc:rights>Copyright &#169; 2000 O'Reilly &amp; Associates, Inc.</dc:rights>
+ <dc:subject>XML</dc:subject>-->
+ </item>
+ <item>
+
+ </item>
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/item_link_normalized.xml b/toolkit/components/feeds/test/xml/rss1/item_link_normalized.xml
new file mode 100644
index 000000000..dbf9749ac
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/item_link_normalized.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed w/ item link
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link.spec == 'http://c.moreover.com/click/here.pl?r123'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ </channel>
+ <item>
+ <title>XML: A Disruptive Technology</title>
+ <link>http://c.moreover.com/click/here.pl?r123</link>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical
+ infrastructure of the Internet.
+ </dc:description>
+ <!-- <dc:publisher>The O'Reilly Network</dc:publisher>
+ <dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>
+ <dc:rights>Copyright &#169; 2000 O'Reilly &amp; Associates, Inc.</dc:rights>
+ <dc:subject>XML</dc:subject>-->
+ </item>
+ <item>
+
+ </item>
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/item_title.xml b/toolkit/components/feeds/test/xml/rss1/item_title.xml
new file mode 100644
index 000000000..b4d4b8e3e
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/item_title.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed w/ item title
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).fields.getProperty('rss1:title') == 'XML: A Disruptive Technology'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ </channel>
+ <item>
+ <title>XML: A Disruptive Technology</title>
+ <!-- <link>http://c.moreover.com/click/here.pl?r123</link>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical
+ infrastructure of the Internet.
+ </dc:description>
+ <dc:publisher>The O'Reilly Network</dc:publisher>
+ <dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>
+ <dc:subject>XML</dc:subject>-->
+ </item>
+ <item>
+
+ </item>
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss1/item_title_normalized.xml b/toolkit/components/feeds/test/xml/rss1/item_title_normalized.xml
new file mode 100644
index 000000000..a9270982f
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/item_title_normalized.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed w/ item title normalized
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).title.text == 'XML: A Disruptive Technology'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ </channel>
+ <item>
+ <title>XML: A Disruptive Technology</title>
+ <link>http://c.moreover.com/click/here.pl?r123</link>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical
+ infrastructure of the Internet.
+ </dc:description>
+ <!-- <dc:publisher>The O'Reilly Network</dc:publisher>
+ <dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>
+ <dc:rights>Copyright &#169; 2000 O'Reilly &amp; Associates, Inc.</dc:rights>
+ <dc:subject>XML</dc:subject>-->
+ </item>
+ <item>
+
+ </item>
+</rdf:RDF>
diff --git a/toolkit/components/feeds/test/xml/rss1/item_updated_dcterms.xml b/toolkit/components/feeds/test/xml/rss1/item_updated_dcterms.xml
new file mode 100644
index 000000000..d8f15ee32
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/item_updated_dcterms.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed updated
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).updated == 'Sat, 07 Sep 2002 00:00:01 GMT'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'
+ xmlns:dcterms='http://purl.org/dc/terms/'>
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ <dcterms:modified>Sat, 07 Sep 2002 00:00:01 GMT</dcterms:modified>
+ </channel>
+ <item rdf:about="http://example.com/hmm">
+ <title>XML: A Disruptive Technology</title>
+ <link>http://c.moreover.com/click/here.pl?r123</link>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical
+ infrastructure of the Internet.
+ </dc:description>
+ <dcterms:modified>Sat, 07 Sep 2002 00:00:01 GMT</dcterms:modified>
+ </item>
+</rdf:RDF>
diff --git a/toolkit/components/feeds/test/xml/rss1/item_wiki_importance_extra_att.xml b/toolkit/components/feeds/test/xml/rss1/item_wiki_importance_extra_att.xml
new file mode 100644
index 000000000..49ba579dd
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss1/item_wiki_importance_extra_att.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: RSS1 feed w/ item wiki:importance with extra attribute
+Expect: feed.items.queryElementAt(1, Components.interfaces.nsIFeedEntry).fields.getProperty('wiki:importance') == 'major'
+
+-->
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+ xmlns:dc='http://purl.org/dc/elements/1.1/'
+ xmlns:w="http://purl.org/rss/1.0/modules/wiki/"
+ xmlns:foo="http://example.org">
+ <channel rdf:about="http://www.xml.com/xml/news.rss">
+ <title>Test</title>
+ <link>http://xml.com/pub</link>
+ <dc:description>another description</dc:description>
+ </channel>
+ <item>
+ <title>XML: A Disruptive Technology</title>
+ <!-- <link>http://c.moreover.com/click/here.pl?r123</link>
+ <dc:description>
+ XML is placing increasingly heavy loads on the existing technical
+ infrastructure of the Internet.
+ </dc:description>
+ <dc:publisher>The O'Reilly Network</dc:publisher>
+ <dc:creator>Simon St.Laurent (mailto:simonstl@simonstl.com)</dc:creator>
+ <dc:rights>Copyright &#169; 2000 O'Reilly &amp; Associates, Inc.</dc:rights>
+ <dc:subject>XML</dc:subject>-->
+ </item>
+ <item>
+ <w:importance foo:bar="baz">major</w:importance>
+ </item>
+</rdf:RDF> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_category.xml b/toolkit/components/feeds/test/xml/rss2/feed_category.xml
new file mode 100644
index 000000000..553825995
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_category.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel category works
+Expect: feed.categories.queryElementAt(0, Components.interfaces.nsIPropertyBag).getProperty('term') == 'hmm'
+
+-->
+<rss version="2.0" >
+<channel>
+<category>hmm</category>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_category_count.xml b/toolkit/components/feeds/test/xml/rss2/feed_category_count.xml
new file mode 100644
index 000000000..881c6e0d9
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_category_count.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel category works w/ domain
+Expect: feed.categories.length == 4
+
+-->
+<rss version="2.0" >
+<channel>
+<category>hmm0</category>
+<category>hmm1</category>
+<category domain="http://example.org">hmm2</category>
+<category>hmm3</category>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_cloud.xml b/toolkit/components/feeds/test/xml/rss2/feed_cloud.xml
new file mode 100644
index 000000000..caa033548
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_cloud.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel cloud works
+Expect: ((feed.cloud.getProperty('domain')=="rpc.sys.com") && (feed.cloud.getProperty('port')=="80") && (feed.cloud.getProperty('path')=="/RPC2") && (feed.cloud.getProperty('registerProcedure')=="pingMe") && (feed.cloud.getProperty('protocol')=="soap"))
+
+-->
+<rss version="2.0" >
+<channel>
+<cloud domain="rpc.sys.com" port="80" path="/RPC2" registerProcedure="pingMe" protocol="soap"/>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_copyright.xml b/toolkit/components/feeds/test/xml/rss2/feed_copyright.xml
new file mode 100644
index 000000000..2d00e7a14
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_copyright.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel copyright works
+Expect: feed.fields.getProperty('copyright') == 'copyright 2006'
+
+-->
+<rss version="2.0" >
+<channel>
+<copyright>copyright 2006</copyright>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_copyright_linebreak.xml b/toolkit/components/feeds/test/xml/rss2/feed_copyright_linebreak.xml
new file mode 100644
index 000000000..4b9ca5e71
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_copyright_linebreak.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel copyright works
+Expect: feed.fields.getProperty('copyright') == 'copyright 2005'
+
+-->
+<rss version="2.0" >
+<channel>
+<copyright>copyright 2005
+
+
+</copyright>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_data_outside_channel.xml b/toolkit/components/feeds/test/xml/rss2/feed_data_outside_channel.xml
new file mode 100644
index 000000000..bf212760d
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_data_outside_channel.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel copyright works
+Expect: feed.fields.getProperty('copyright') == 'copyright 2006'
+
+-->
+<rss version="2.0" >
+<dc:creator xmlns:dc="http://example.org">heynow</dc:creator>
+<channel>
+<copyright>copyright 2006</copyright>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_dc_contributor.xml b/toolkit/components/feeds/test/xml/rss2/feed_dc_contributor.xml
new file mode 100644
index 000000000..cfb514ccd
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_dc_contributor.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel copyright works
+Expect: feed.contributors.queryElementAt(0, Components.interfaces.nsIFeedPerson).name == 'them';
+
+-->
+<rss version="2.0" >
+<channel xmlns:dc="http://purl.org/dc/elements/1.1/">
+<copyright>copyright 2006</copyright>
+<dc:creator>me</dc:creator>
+<dc:contributor>them</dc:contributor>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_dc_creator.xml b/toolkit/components/feeds/test/xml/rss2/feed_dc_creator.xml
new file mode 100644
index 000000000..8ed1aff7f
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_dc_creator.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel copyright works
+Expect: feed.authors.queryElementAt(0, Components.interfaces.nsIFeedPerson).name == 'me'
+
+-->
+<rss version="2.0" >
+<channel xmlns:dc="http://purl.org/dc/elements/1.1/">
+<copyright>copyright 2006</copyright>
+<dc:creator>me</dc:creator>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_description.xml b/toolkit/components/feeds/test/xml/rss2/feed_description.xml
new file mode 100644
index 000000000..11463dfe0
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_description.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel description works
+Expect: var desc = feed.fields.getProperty('description'); desc == 'test';
+
+-->
+<rss version="2.0" >
+<channel>
+<description>test</description>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_description_html.xml b/toolkit/components/feeds/test/xml/rss2/feed_description_html.xml
new file mode 100644
index 000000000..ecb544f6c
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_description_html.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel description works w/html
+Expect: feed.fields.getProperty('description') == '<b>test</b>'
+
+-->
+<rss version="2.0" >
+<channel>
+<description>&lt;b>test&lt;/b></description>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_description_html_cdata.xml b/toolkit/components/feeds/test/xml/rss2/feed_description_html_cdata.xml
new file mode 100644
index 000000000..45ee9e92b
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_description_html_cdata.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel description works w/ html & CDATA
+Expect: feed.fields.getProperty('description') == '<b>test</b>'
+
+-->
+<rss version="2.0" >
+<channel>
+<description><![CDATA[<b>test</b>]]></description>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_docs.xml b/toolkit/components/feeds/test/xml/rss2/feed_docs.xml
new file mode 100644
index 000000000..20323b22f
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_docs.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel docs works
+Expect: feed.fields.getProperty('docs') == 'http://example.org'
+
+-->
+<rss version="2.0" >
+<channel>
+<docs>http://example.org</docs>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_generator.xml b/toolkit/components/feeds/test/xml/rss2/feed_generator.xml
new file mode 100644
index 000000000..91ba579b4
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_generator.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel generator works
+Expect: feed.generator.agent == 'a generator used to make feeds'
+
+-->
+<rss version="2.0" >
+<channel>
+<generator>a generator used to make feeds</generator>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_image_desc.xml b/toolkit/components/feeds/test/xml/rss2/feed_image_desc.xml
new file mode 100644
index 000000000..7f665641b
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_image_desc.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel image description and required fields work
+Expect: ((feed.image.getProperty('title') == 'A picture') && (feed.image.getProperty('link') == 'http://example.org') && (feed.image.getProperty('url') == 'http://example.org/a.jpg') && (feed.image.getProperty('description') == 'Yo!'))
+
+-->
+<rss version="2.0" >
+<channel>
+<image>
+ <link>http://example.org</link>
+ <title>A picture</title>
+ <url>http://example.org/a.jpg</url>
+ <description>Yo!</description>
+</image>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_image_desc_width_height.xml b/toolkit/components/feeds/test/xml/rss2/feed_image_desc_width_height.xml
new file mode 100644
index 000000000..2be53e86c
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_image_desc_width_height.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel image required fields work
+Expect: ((feed.image.getProperty('title') == 'A picture') && (feed.image.getProperty('link') == 'http://example.org') && (feed.image.getProperty('url') == 'http://example.org/a.jpg') && (feed.image.getProperty('description') == 'Yo!') && (feed.image.getProperty('width') == '42') && (feed.image.getProperty('height') == '43'))
+
+-->
+<rss version="2.0" >
+<channel>
+<image>
+ <link>http://example.org</link>
+ <title>A picture</title>
+ <url>http://example.org/a.jpg</url>
+ <description>Yo!</description>
+ <width>42</width>
+ <height>43</height>
+</image>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_image_required.xml b/toolkit/components/feeds/test/xml/rss2/feed_image_required.xml
new file mode 100644
index 000000000..9035523a1
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_image_required.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel image required fields work
+Expect: ((feed.image.getProperty('title') == 'A picture') && (feed.image.getProperty('link') == 'http://example.org') && (feed.image.getProperty('url') == 'http://example.org/a.jpg'))
+
+-->
+<rss version="2.0" >
+<channel>
+<image>
+ <link>http://example.org</link>
+ <title>A picture</title>
+ <url>http://example.org/a.jpg</url>
+</image>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_language.xml b/toolkit/components/feeds/test/xml/rss2/feed_language.xml
new file mode 100644
index 000000000..d4047a99f
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_language.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel language works
+Expect: feed.fields.getProperty('language') == 'en-us'
+
+-->
+<rss version="2.0" >
+<channel>
+<language>en-us</language>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_lastBuildDate.xml b/toolkit/components/feeds/test/xml/rss2/feed_lastBuildDate.xml
new file mode 100644
index 000000000..fee9ff582
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_lastBuildDate.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel lastBuildDate works
+Expect: feed.fields.getProperty('lastBuildDate') == 'Sat, 07 Sep 2002 00:00:01 GMT'
+
+-->
+<rss version="2.0" >
+<channel>
+<lastBuildDate>Sat, 07 Sep 2002 00:00:01 GMT</lastBuildDate>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_linebreak_link.xml b/toolkit/components/feeds/test/xml/rss2/feed_linebreak_link.xml
new file mode 100644
index 000000000..1af6550f9
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_linebreak_link.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel link works w/ line break
+Expect: feed.link.spec == 'http://mozilla.org/'
+
+-->
+<rss version="2.0" >
+<channel>
+<link>
+http://mozilla.org/
+</link>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_link.xml b/toolkit/components/feeds/test/xml/rss2/feed_link.xml
new file mode 100644
index 000000000..a4874e9ca
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_link.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel link works
+Expect: feed.link.spec == 'http://mozilla.org/'
+
+-->
+<rss version="2.0" >
+<channel>
+<link>http://mozilla.org/</link>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_link_cdata.xml b/toolkit/components/feeds/test/xml/rss2/feed_link_cdata.xml
new file mode 100644
index 000000000..5031ac1c3
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_link_cdata.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel link works w/ CDATA
+Expect: feed.link.spec == 'http://mozilla.org/'
+
+-->
+<rss version="2.0" >
+<channel>
+<link>
+ <![CDATA[http://mozilla.org/]]>
+</link>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_managingEditor.xml b/toolkit/components/feeds/test/xml/rss2/feed_managingEditor.xml
new file mode 100644
index 000000000..3f7060449
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_managingEditor.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel managingEditor works
+Expect: feed.authors.queryElementAt(0, Components.interfaces.nsIFeedPerson).email == 'example@example.com'
+
+-->
+<rss version="2.0" >
+<channel>
+<managingEditor>example@example.com</managingEditor>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_managingEditor_extra_att.xml b/toolkit/components/feeds/test/xml/rss2/feed_managingEditor_extra_att.xml
new file mode 100644
index 000000000..017a4595f
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_managingEditor_extra_att.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel managingEditor works
+Expect: feed.authors.queryElementAt(0, Components.interfaces.nsIFeedPerson).email == 'example@example.com'
+
+-->
+<rss version="2.0" >
+<channel>
+<managingEditor foo:bar="baz" xmlns:foo="http://example.org">example@example.com</managingEditor>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_multiple_categories.xml b/toolkit/components/feeds/test/xml/rss2/feed_multiple_categories.xml
new file mode 100644
index 000000000..538362b6a
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_multiple_categories.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel category works
+Expect: feed.categories.queryElementAt(2, Components.interfaces.nsIPropertyBag).getProperty('term') == 'hmm2'
+
+-->
+<rss version="2.0" >
+<channel>
+<category>hmm0</category>
+<category>hmm1</category>
+<category>hmm2</category>
+<category>hmm3</category>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_pubDate.xml b/toolkit/components/feeds/test/xml/rss2/feed_pubDate.xml
new file mode 100644
index 000000000..42cea6832
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_pubDate.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel pubDate works
+Expect: feed.fields.getProperty('pubDate') == 'Sat, 07 Sep 2002 00:00:01 GMT'
+
+-->
+<rss version="2.0" >
+<channel>
+<pubDate>Sat, 07 Sep 2002 00:00:01 GMT</pubDate>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_pubDate_invalid.xml b/toolkit/components/feeds/test/xml/rss2/feed_pubDate_invalid.xml
new file mode 100644
index 000000000..48cce256a
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_pubDate_invalid.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: non-RFC822 date should produce null feed.updated
+Expect: feed.updated == null
+
+-->
+<rss version="2.0" >
+<channel>
+<pubDate>Satmonkey, 07 Sepmonkey 2002 00:00:01 GMT</pubDate>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_pubDate_nonRFC822_1.xml b/toolkit/components/feeds/test/xml/rss2/feed_pubDate_nonRFC822_1.xml
new file mode 100644
index 000000000..846ef22a6
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_pubDate_nonRFC822_1.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: Test whether date parsing handles partly-abbreviated dates.
+Expect: feed.updated == 'Tue, 25 Apr 2006 08:00:00 GMT'
+
+-->
+<rss version="2.0" >
+<channel>
+<pubDate>Tues, 25 Apri 2006 08:00:00 GMT</pubDate>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_pubDate_nonRFC822_2.xml b/toolkit/components/feeds/test/xml/rss2/feed_pubDate_nonRFC822_2.xml
new file mode 100644
index 000000000..d1ee96f36
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_pubDate_nonRFC822_2.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: Test whether date parsing handles unabbreviated dates.
+Expect: feed.updated == 'Sat, 25 Nov 2006 00:12:45 GMT'
+
+-->
+<rss version="2.0" >
+<channel>
+<pubDate>Saturday 25 November 2006 10:12:45 +1000</pubDate>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_pubDate_timezoneZ.xml b/toolkit/components/feeds/test/xml/rss2/feed_pubDate_timezoneZ.xml
new file mode 100644
index 000000000..b31ed5c56
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_pubDate_timezoneZ.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: Test whether date parsing handles "Z" as a timezone in RFC822.
+Expect: feed.updated == 'Tue, 25 Apr 2006 08:00:00 GMT'
+
+-->
+<rss version="2.0" >
+<channel>
+<pubDate>Tue, 25 Apr 2006 08:00:00 Z</pubDate>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_pubDate_utc.xml b/toolkit/components/feeds/test/xml/rss2/feed_pubDate_utc.xml
new file mode 100644
index 000000000..8eff56046
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_pubDate_utc.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: Test whether date parsing handles 'UTC' as a timezone.
+Expect: feed.updated == 'Mon, 16 Apr 2007 03:12:45 GMT'
+
+-->
+<rss version="2.0" >
+<channel>
+<pubDate>Monday, 16 April 2007 03:12:45 UTC</pubDate>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_rating.xml b/toolkit/components/feeds/test/xml/rss2/feed_rating.xml
new file mode 100644
index 000000000..dd5f8f9e5
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_rating.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel rating works
+Expect: feed.fields.getProperty('rating') == '(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l by "webmaster@example.com" on "2006.01.29T10:09-0800" r (n 0 s 0 v 0 l 0))'
+
+-->
+<rss version="2.0" >
+<channel>
+<rating>(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l by "webmaster@example.com" on "2006.01.29T10:09-0800" r (n 0 s 0 v 0 l 0))</rating>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_single_quote_stylesheet_pi.xml b/toolkit/components/feeds/test/xml/rss2/feed_single_quote_stylesheet_pi.xml
new file mode 100644
index 000000000..10141fe7e
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_single_quote_stylesheet_pi.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!--
+
+Description: stylesheets with single quoted attributes work. Bug 352549.
+Base: http://www.penny-arcade.com/rss.xml
+Expect: result.stylesheet.spec == "http://www.penny-arcade.com/stylesheets/rss-display.xsl"
+
+-->
+<?xml-stylesheet type='text/xsl' href='/stylesheets/rss-display.xsl' version='1.0'?>
+<rss version="2.0">
+<channel>
+<title>Penny-Arcade</title>
+<link>http://www.penny-arcade.com/</link>
+<language>en-us</language>
+
+<copyright>Copyright 1999 - 2006 Penny Arcade, Inc.</copyright>
+<image>
+<url>http://www.penny-arcade.com/images/rss-logo.png</url>
+<title>Penny-Arcade Logo</title>
+<link>http://www.penny-arcade.com/</link>
+<width>144</width>
+
+<height>82</height>
+</image>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_skipDays.xml b/toolkit/components/feeds/test/xml/rss2/feed_skipDays.xml
new file mode 100644
index 000000000..8c6ffa9e4
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_skipDays.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel skipDays works
+Expect: ((feed.skipDays.queryElementAt(0, Components.interfaces.nsISupportsString) == 'Sunday') && (feed.skipDays.queryElementAt(1, Components.interfaces.nsISupportsString) == 'Monday'))
+
+-->
+<rss version="2.0" >
+<channel>
+<skipDays>
+ <day>Sunday</day>
+ <day>Monday</day>
+</skipDays>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_skipHours.xml b/toolkit/components/feeds/test/xml/rss2/feed_skipHours.xml
new file mode 100644
index 000000000..a20372eda
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_skipHours.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel skipHours works
+Expect: ((feed.skipHours.queryElementAt(0, Components.interfaces.nsISupportsString) == '0') && (feed.skipHours.queryElementAt(4, Components.interfaces.nsISupportsString) == '23'))
+
+-->
+<rss version="2.0" >
+<channel>
+<skipHours>
+ <hour>0</hour>
+ <hour>1</hour>
+ <hour>2</hour>
+ <hour>22</hour>
+ <hour>23</hour>
+</skipHours>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_subtitle.xml b/toolkit/components/feeds/test/xml/rss2/feed_subtitle.xml
new file mode 100644
index 000000000..a98a3c19e
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_subtitle.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel description works
+Expect: feed.subtitle.text == 'test'
+
+-->
+<rss version="2.0" >
+<channel>
+<description>test</description>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_subtitle_html.xml b/toolkit/components/feeds/test/xml/rss2/feed_subtitle_html.xml
new file mode 100644
index 000000000..fca819d36
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_subtitle_html.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel description works
+Expect: feed.subtitle.plainText() == '<i><b>test</b></i>'
+
+-->
+<rss version="2.0" >
+<channel>
+<description><![CDATA[<i><b>test</b></i>]]></description>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_subtitle_markup_stripped.xml b/toolkit/components/feeds/test/xml/rss2/feed_subtitle_markup_stripped.xml
new file mode 100644
index 000000000..54f6a623c
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_subtitle_markup_stripped.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel description markup is not HTML
+Expect: feed.subtitle.plainText() == '<i><b>test</b></i>'
+
+-->
+<rss version="2.0" >
+<channel>
+<description><![CDATA[<i><b>test</b></i>]]></description>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_textinput.xml b/toolkit/components/feeds/test/xml/rss2/feed_textinput.xml
new file mode 100644
index 000000000..4617d62bc
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_textinput.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel textInput works
+Expect: ((feed.textInput.getProperty('description') == 'Your aggregator supports the textInput element. What software are you using?') && (feed.textInput.getProperty('link') == 'http://www.cadenhead.org/textinput.php') && (feed.textInput.getProperty('name') == 'query') && (feed.textInput.getProperty('title') == 'TextInput Inquiry'))
+
+-->
+<rss version="2.0" >
+<channel>
+<textInput>
+ <description>Your aggregator supports the textInput element. What software are you using?</description>
+ <link>http://www.cadenhead.org/textinput.php</link>
+ <name>query</name>
+ <title>TextInput Inquiry</title>
+</textInput>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_title.xml b/toolkit/components/feeds/test/xml/rss2/feed_title.xml
new file mode 100644
index 000000000..1f7d63ad2
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_title.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel title works
+Expect: feed.title.plainText() == 'test title'
+
+-->
+<rss version="2.0" >
+<channel>
+<title>test title</title>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_title_cdata_mixed.xml b/toolkit/components/feeds/test/xml/rss2/feed_title_cdata_mixed.xml
new file mode 100644
index 000000000..19ef62915
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_title_cdata_mixed.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel title works w/ funky CDATA title
+Expect: feed.title.plainText() == 'test title'
+
+-->
+<rss version="2.0" >
+<channel>
+<title>test t<![CDATA[it]]>le</title>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_title_nesting.xml b/toolkit/components/feeds/test/xml/rss2/feed_title_nesting.xml
new file mode 100644
index 000000000..82492cef7
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_title_nesting.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel title works w/ nested title
+Expect: feed.title.text == 'test title'
+
+-->
+<rss version="2.0" >
+<channel>
+<title>test title</title>
+<bogus><title>bogus title</title></bogus>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_ttl.xml b/toolkit/components/feeds/test/xml/rss2/feed_ttl.xml
new file mode 100644
index 000000000..57158aff4
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_ttl.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel ttl works
+Expect: feed.fields.getProperty('ttl') == '60'
+
+-->
+<rss version="2.0" >
+<channel>
+<ttl>60</ttl>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_updated.xml b/toolkit/components/feeds/test/xml/rss2/feed_updated.xml
new file mode 100644
index 000000000..c9e75e360
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_updated.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel pubDate works
+Expect: feed.updated == 'Sat, 07 Sep 2002 00:00:01 GMT'
+
+-->
+<rss version="2.0" >
+<channel>
+<pubDate>Sat, 07 Sep 2002 00:00:01 GMT</pubDate>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_updated_dcdate.xml b/toolkit/components/feeds/test/xml/rss2/feed_updated_dcdate.xml
new file mode 100644
index 000000000..aa69e7800
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_updated_dcdate.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel pubDate works
+Expect: feed.updated == 'Sat, 07 Sep 2002 00:00:01 GMT'
+
+-->
+<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<channel>
+<dc:date>Sat, 07 Sep 2002 00:00:01 GMT</dc:date>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_updated_lastBuildDate.xml b/toolkit/components/feeds/test/xml/rss2/feed_updated_lastBuildDate.xml
new file mode 100644
index 000000000..2fb24a7ec
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_updated_lastBuildDate.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel lastBuildDate works
+Expect: feed.updated == 'Sat, 07 Sep 2002 00:00:01 GMT'
+
+-->
+<rss version="2.0" >
+<channel>
+<lastBuildDate>Sat, 07 Sep 2002 00:00:01 GMT</lastBuildDate>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_updated_lastBuildDate_priority.xml b/toolkit/components/feeds/test/xml/rss2/feed_updated_lastBuildDate_priority.xml
new file mode 100644
index 000000000..24f024005
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_updated_lastBuildDate_priority.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel lastBuildDate trumps pubDate
+Expect: feed.updated == 'Sat, 07 Sep 2002 00:00:01 GMT'
+
+-->
+<rss version="2.0" >
+<channel>
+<pubDate>Sun, 08 Sep 2002 00:00:01 GMT</pubDate>
+<lastBuildDate>Sat, 07 Sep 2002 00:00:01 GMT</lastBuildDate>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_webMaster.xml b/toolkit/components/feeds/test/xml/rss2/feed_webMaster.xml
new file mode 100644
index 000000000..887894983
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_webMaster.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel webMaster works
+Expect: feed.fields.getProperty('webMaster') == 'example@example.com'
+
+-->
+<rss version="2.0" >
+<channel>
+<webMaster>example@example.com</webMaster>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_wfw_commentapi.xml b/toolkit/components/feeds/test/xml/rss2/feed_wfw_commentapi.xml
new file mode 100644
index 000000000..af725064e
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_wfw_commentapi.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel copyright works
+Expect: feed.fields.getProperty('wfw:comment') == 'http://example.org'
+
+-->
+<rss xmlns:wfw="http://wellformedweb.org/CommentAPI/" version="2.0" >
+<channel xmlns:dc="http://purl.org/dc/elements/1.1/">
+<wfw:comment>http://example.org</wfw:comment>
+<copyright>copyright 2006</copyright>
+<dc:creator>me</dc:creator>
+<dc:contributor>them</dc:contributor>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_wfw_commentrss.xml b/toolkit/components/feeds/test/xml/rss2/feed_wfw_commentrss.xml
new file mode 100644
index 000000000..fb1d89609
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_wfw_commentrss.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel copyright works
+Expect: feed.fields.getProperty('wfw:commentRss') == 'http://example.org'
+
+-->
+<rss xmlns:wfw="http://wellformedweb.org/CommentAPI/" version="2.0" >
+<channel xmlns:dc="http://purl.org/dc/elements/1.1/">
+<copyright>copyright 2006</copyright>
+<dc:creator>me</dc:creator>
+<wfw:commentRss>http://example.org</wfw:commentRss>
+<dc:contributor>them</dc:contributor>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_wiki.xml b/toolkit/components/feeds/test/xml/rss2/feed_wiki.xml
new file mode 100644
index 000000000..b8cb783b0
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_wiki.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel unusual prefixed ext works
+Expect: feed.fields.getProperty('wiki:version') == '1'
+
+-->
+<rss
+xmlns:w='http://purl.org/rss/1.0/modules/wiki/'
+xmlns:wfw="http://wellformedweb.org/CommentAPI/" version="2.0" >
+<channel xmlns:dc="http://purl.org/dc/elements/1.1/">
+<copyright>copyright 2006</copyright>
+<dc:creator>me</dc:creator>
+<w:version>1</w:version>
+<wfw:commentRss>http://example.org</wfw:commentRss>
+<dc:contributor>them</dc:contributor>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/feed_wiki_unusual_prefix.xml b/toolkit/components/feeds/test/xml/rss2/feed_wiki_unusual_prefix.xml
new file mode 100644
index 000000000..b8cb783b0
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/feed_wiki_unusual_prefix.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel unusual prefixed ext works
+Expect: feed.fields.getProperty('wiki:version') == '1'
+
+-->
+<rss
+xmlns:w='http://purl.org/rss/1.0/modules/wiki/'
+xmlns:wfw="http://wellformedweb.org/CommentAPI/" version="2.0" >
+<channel xmlns:dc="http://purl.org/dc/elements/1.1/">
+<copyright>copyright 2006</copyright>
+<dc:creator>me</dc:creator>
+<w:version>1</w:version>
+<wfw:commentRss>http://example.org</wfw:commentRss>
+<dc:contributor>them</dc:contributor>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/item_author.xml b/toolkit/components/feeds/test/xml/rss2/item_author.xml
new file mode 100644
index 000000000..ad0c97e2a
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_author.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item author works
+Expect: var authors = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).authors; var author = authors.queryElementAt(0, Components.interfaces.nsIFeedPerson); ((author.name == 'Joe Bob Briggs'));
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<title>test</title>
+</item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_category.xml b/toolkit/components/feeds/test/xml/rss2/item_category.xml
new file mode 100644
index 000000000..4795e00bb
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_category.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item category works
+Expect: var cats = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).fields.getProperty('categories'); cats.QueryInterface(Components.interfaces.nsIArray); var cat = cats.queryElementAt(0, Components.interfaces.nsIPropertyBag); ((cat.getProperty('domain') == 'foo') && (cat.getProperty('term') == 'bar'));
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<title>test</title>
+<category domain="foo">bar</category>
+</item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_comments.xml b/toolkit/components/feeds/test/xml/rss2/item_comments.xml
new file mode 100644
index 000000000..da1cccc82
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_comments.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item comments works
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).fields.getProperty('comments') == 'http://example.org'
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+<title>test</title>
+<!--<author>jbb@dallas.example.com (Joe Bob Briggs)</author>-->
+<comments>http://example.org</comments>
+
+<category domain="foo">bar</category>
+
+</item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_content_encoded.xml b/toolkit/components/feeds/test/xml/rss2/item_content_encoded.xml
new file mode 100644
index 000000000..6611375b6
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_content_encoded.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item title works
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).content.plainText() == 'foobar'
+
+-->
+<rss version="2.0" >
+<channel>
+<item xmlns:c="http://purl.org/rss/1.0/modules/content/">
+ <title>test</title>
+ <c:encoded>foobar</c:encoded>
+</item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_count.xml b/toolkit/components/feeds/test/xml/rss2/item_count.xml
new file mode 100644
index 000000000..a69cbc979
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_count.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: items length is correct
+Expect: feed.items.length == 1
+
+-->
+<rss version="2.0"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+
+<channel>
+<title>Items Test</title>
+<link>http://mozilla.org/</link>
+<description></description>
+
+<dc:language>en-us</dc:language>
+<dc:creator>sayrer@gmail.com</dc:creator>
+<dc:date>2005-12-07T14:48:03-05:00</dc:date>
+
+<item>
+<title>Is the date right?</title>
+<link>http://example.org/dc_date.html</link>
+</item>
+
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/item_count2.xml b/toolkit/components/feeds/test/xml/rss2/item_count2.xml
new file mode 100644
index 000000000..27df0a932
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_count2.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: items length is correct
+Expect: feed.items.length == 2
+
+-->
+<rss version="2.0"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+
+<channel>
+<title>Items Test</title>
+<link>http://mozilla.org/</link>
+<description></description>
+
+<dc:language>en-us</dc:language>
+<dc:creator>sayrer@gmail.com</dc:creator>
+<dc:date>2005-12-07T14:48:03-05:00</dc:date>
+
+<item>
+<title>Is the date right?</title>
+<link>http://example.org/dc_date.html</link>
+</item>
+<item>
+<title>Is the date right?</title>
+<link>http://example.org/dc_date.html</link>
+</item>
+
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/item_description.xml b/toolkit/components/feeds/test/xml/rss2/item_description.xml
new file mode 100644
index 000000000..7416d48e6
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_description.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item desc encoded works
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).summary.text == 'I\'m headed for France. I wasn\'t gonna go this year, but then last week <a href="http://www.imdb.com/title/tt0086525/">Valley Girl</a> came out and I said to myself, Joe Bob, you gotta get out of the country for a while.'
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+<comments>http://example.org</comments>
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<title>test</title>
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_description_2.xml b/toolkit/components/feeds/test/xml/rss2/item_description_2.xml
new file mode 100644
index 000000000..427726868
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_description_2.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item desc encoded works
+Expect: feed.items.queryElementAt(1, Components.interfaces.nsIFeedEntry).summary.text == 'I\'m headed for France. I wasn\'t gonna go this year, but then last week <a href="http://www.imdb.com/title/tt0086525/">Valley Girl</a> came out and I said to myself, Joe Bob, you gotta get out of the country for a while.'
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+ <description>hmmm</description>
+</item>
+<item>
+<comments>http://example.org</comments>
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<title>test</title>
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_description_cdata.xml b/toolkit/components/feeds/test/xml/rss2/item_description_cdata.xml
new file mode 100644
index 000000000..ef3926f87
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_description_cdata.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item desc CDATA works
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).summary.text == 'I\'m headed for France. I wasn\'t gonna go this year, but then last week <a href="http://www.imdb.com/title/tt0086525/">Valley Girl</a> came out and I said to myself, Joe Bob, you gotta get out of the country for a while.'
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test</title>
+
+<category domain="foo">bar</category>
+<description><![CDATA[I'm headed for France. I wasn't gonna go this year, but then last week <a href="http://www.imdb.com/title/tt0086525/">Valley Girl</a> came out and I said to myself, Joe Bob, you gotta get out of the country for a while.]]></description>
+</item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_description_decode_entities.xml b/toolkit/components/feeds/test/xml/rss2/item_description_decode_entities.xml
new file mode 100644
index 000000000..e259354dc
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_description_decode_entities.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Description: item desc encoded, double-escaped entity
+Expect: var summary = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).summary; summary.plainText() == "test D\u00e9sol\u00e9e";
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+<comments>http://example.org</comments>
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<title>test</title>
+<category domain="foo">bar</category>
+
+<description>
+ &lt;b>test D&amp;eacute;sol&amp;eacute;e&lt;/b>
+</description>
+</item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_description_normalized.xml b/toolkit/components/feeds/test/xml/rss2/item_description_normalized.xml
new file mode 100644
index 000000000..9819deb36
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_description_normalized.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item desc encoded, normalied works
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).summary.text == 'I\'m headed for France. I wasn\'t gonna go this year, but then last week <a href="http://www.imdb.com/title/tt0086525/">Valley Girl</a> came out and I said to myself, Joe Bob, you gotta get out of the country for a while.'
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+<comments>http://example.org</comments>
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<title>test</title>
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_description_normalized_nohtml.xml b/toolkit/components/feeds/test/xml/rss2/item_description_normalized_nohtml.xml
new file mode 100644
index 000000000..0a34a008d
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_description_normalized_nohtml.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item desc encoded, normalized works
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).summary.plainText() == 'I\'m headed for France. I wasn\'t gonna go this year, but then last week Valley Girl came out and I said to myself, Joe Bob, you gotta get out of the country for a while.'
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+<comments>http://example.org</comments>
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<title>test</title>
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_enclosure.xml b/toolkit/components/feeds/test/xml/rss2/item_enclosure.xml
new file mode 100644
index 000000000..2e38a370a
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_enclosure.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item enclosure works
+Expect: var enc = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).fields.getProperty('enclosure'); enc.QueryInterface(Components.interfaces.nsIPropertyBag); ((enc.getProperty('length') == '24986239') && (enc.getProperty('type') == 'audio/mpeg') && (enc.getProperty('url') == 'http://dallas.example.com/joebob_050689.mp3') && (feed.type == 1) && (feed.enclosureCount == 1));
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+
+<enclosure length="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test</title>
+
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_enclosure_duplicates.xml b/toolkit/components/feeds/test/xml/rss2/item_enclosure_duplicates.xml
new file mode 100644
index 000000000..a9bcd2cc9
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_enclosure_duplicates.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: feed with duplicate enclosures on a single item
+Expect: ((feed.type == 4) && (feed.enclosureCount == 1));
+
+-->
+<rss xmlns:media="http://search.yahoo.com/mrss" version="2.0" >
+<channel>
+
+<item>
+<enclosure length="24986239" type="video/mpeg" url="http://dallas.example.com/joebob_050689.mpeg" />
+<media:content fileSize="24986239" type="video/mpeg" url="http://dallas.example.com/joebob_050689.mpeg" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test audio</title>
+
+<category domain="foo">bar</category>
+
+<description>Listen to the words that are coming out of my mouth.</description>
+</item>
+
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_enclosure_duplicates2.xml b/toolkit/components/feeds/test/xml/rss2/item_enclosure_duplicates2.xml
new file mode 100644
index 000000000..51f7caba9
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_enclosure_duplicates2.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: feed with duplicate enclosures on a single item with different data available
+Expect: var enc = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).fields.getProperty('enclosure'); enc.QueryInterface(Components.interfaces.nsIPropertyBag); ((enc.getProperty('length') == '24986239') && (enc.getProperty('type') == 'video/mpeg') && (feed.type == 4) && (feed.enclosureCount == 1) );
+
+-->
+<rss xmlns:media="http://search.yahoo.com/mrss" version="2.0" >
+<channel>
+
+<item>
+<enclosure url="http://dallas.example.com/joebob_050689.mpeg" />
+<media:content fileSize="24986239" type="video/mpeg" url="http://dallas.example.com/joebob_050689.mpeg" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test audio</title>
+
+<category domain="foo">bar</category>
+
+<description>Listen to the words that are coming out of my mouth.</description>
+</item>
+
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_enclosure_mixed.xml b/toolkit/components/feeds/test/xml/rss2/item_enclosure_mixed.xml
new file mode 100644
index 000000000..7b49e4d74
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_enclosure_mixed.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: feed with different kinds of enclosures that should be TYPE_FEED (0)
+Expect: ((feed.type == 0) && (feed.enclosureCount == 2));
+
+-->
+<rss version="2.0" >
+<channel>
+
+<item>
+<enclosure length="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test audio</title>
+
+<category domain="foo">bar</category>
+
+<description>Listen to the words that are coming out of my mouth.</description>
+</item>
+
+<item>
+<enclosure length="3000000" type="video/mpeg" url="http://dallas.example.com/joebob_pants.mpeg" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test video</title>
+
+<category domain="foo">bar</category>
+
+<description>Look into my eyes....</description>
+</item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_enclosure_mixed2.xml b/toolkit/components/feeds/test/xml/rss2/item_enclosure_mixed2.xml
new file mode 100644
index 000000000..a54a40559
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_enclosure_mixed2.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: feed that doesn't have at least one enclosure per entry should be TYPE_FEED (0)
+Expect: ((feed.type == 0) && (feed.enclosureCount == 1));
+
+-->
+<rss version="2.0" >
+<channel>
+
+<item>
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>no video this week!</title>
+
+<category domain="foo">bar</category>
+
+<description>I'm on a trip to the moon this week for this year's Spaceshot Vlogger
+conference. No video this week!</description>
+</item>
+
+<item>
+<enclosure length="3000000" type="video/mpeg" url="http://dallas.example.com/joebob_pants.mpeg" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>orange keyboard</title>
+
+<category domain="foo">bar</category>
+
+<description>Crazy things happen when you paint your keyboard orange.</description>
+</item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_guid.xml b/toolkit/components/feeds/test/xml/rss2/item_guid.xml
new file mode 100644
index 000000000..2e7f551ef
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_guid.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item guid works
+Expect: var guid = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).fields.getProperty('guid'); guid.QueryInterface(Components.interfaces.nsIPropertyBag2); guid.getProperty('guid') == 'asdf';
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+
+<enclosure length="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test</title>
+<guid>asdf</guid>
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/item_guid_bogus_url.xml b/toolkit/components/feeds/test/xml/rss2/item_guid_bogus_url.xml
new file mode 100644
index 000000000..2f1b67ced
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_guid_bogus_url.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item copes with bogus guid
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link == null;
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+
+<enclosure length="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test</title>
+<guid isPermaLink="true">xorg</guid>
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink.xml b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink.xml
new file mode 100644
index 000000000..c64341427
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item guid works
+Expect: var link = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link; link.spec == 'http://www.example.org/';
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+
+<enclosure length="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<title>test</title>
+<guid isPermaLink="true">http://www.example.org/</guid>
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_default.xml b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_default.xml
new file mode 100644
index 000000000..7d6ae7958
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_default.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item guid works
+Expect: var link = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link; link.spec == 'http://www.example.org/';
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+
+<enclosure length="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<title>test</title>
+<guid>http://www.example.org/</guid>
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false.xml b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false.xml
new file mode 100644
index 000000000..c2a1ad867
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item guid should not map to link when isPermaLink=false
+Expect: var link = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link; link == null;
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+
+<enclosure length="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<title>test</title>
+<guid isPermaLink="false">http://www.example.org/</guid>
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false_uppercase.xml b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false_uppercase.xml
new file mode 100644
index 000000000..9ff2505c4
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_false_uppercase.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item guid should not map to link when isPermaLink=FaLsE
+Expect: var link = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link; link == null;
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+
+<enclosure length="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<title>test</title>
+<guid isPermaLink="FaLsE">http://www.example.org/</guid>
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_true_uppercase.xml b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_true_uppercase.xml
new file mode 100644
index 000000000..bc4fdc0e9
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_true_uppercase.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item guid should map to link when isPermaLink=TrUe
+Expect: var link = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link; link.spec == "http://www.example.org/";
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+
+<enclosure length="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<title>test</title>
+<guid isPermaLink="TrUe">http://www.example.org/</guid>
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_unknown_value.xml b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_unknown_value.xml
new file mode 100644
index 000000000..4dce8c390
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_guid_isPermaLink_unknown_value.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item guid should map to link when isPermaLink=meatcake or other unknown values
+Expect: var link = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link; link.spec == "http://www.example.org/";
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+
+<enclosure length="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<title>test</title>
+<guid isPermaLink="meatcake">http://www.example.org/</guid>
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_guid_normalized.xml b/toolkit/components/feeds/test/xml/rss2/item_guid_normalized.xml
new file mode 100644
index 000000000..e4ac97862
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_guid_normalized.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item guid works
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).id == 'asdf';
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+
+<enclosure length="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test</title>
+<guid>asdf</guid>
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_guid_with_link.xml b/toolkit/components/feeds/test/xml/rss2/item_guid_with_link.xml
new file mode 100644
index 000000000..d2d3daca5
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_guid_with_link.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item prefers link to guid
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link.spec == 'http://link.example.org/';
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+
+<enclosure length="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test</title>
+<guid isPermaLink="true">http://www.example.org</guid>
+<link>http://link.example.org/</link>
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_link.xml b/toolkit/components/feeds/test/xml/rss2/item_link.xml
new file mode 100644
index 000000000..c89f71e77
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_link.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item comments works
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).fields.getProperty('link') == 'http://dallas.example.com/1983/05/06/joebob.htm'
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+<title>test</title>
+<!--<author>jbb@dallas.example.com (Joe Bob Briggs)</author>-->
+<comments>http://example.org</comments>
+<link>http://dallas.example.com/1983/05/06/joebob.htm</link>
+<category domain="foo">bar</category>
+
+</item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_link_normalized.xml b/toolkit/components/feeds/test/xml/rss2/item_link_normalized.xml
new file mode 100644
index 000000000..876d7613c
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_link_normalized.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item link normalized works
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).link.spec == 'http://dallas.example.com/1983/05/06/joebob.htm'
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+<title>test</title>
+<!--<author>jbb@dallas.example.com (Joe Bob Briggs)</author>-->
+<comments>http://example.org</comments>
+<link>http://dallas.example.com/1983/05/06/joebob.htm</link>
+<category domain="foo">bar</category>
+
+</item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_plain_desc.xml b/toolkit/components/feeds/test/xml/rss2/item_plain_desc.xml
new file mode 100644
index 000000000..ffb4226f1
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_plain_desc.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item desc plain text works
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).summary.text == "I'm headed for France. I wasn't gonna go this year, but then last week \"Valley Girl\" came out and I said to myself, Joe Bob, you gotta get out of the country for a while."
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test</title>
+
+<category domain="foo">bar</category>
+<description>I'm headed for France. I wasn't gonna go this year, but then last week "Valley Girl" came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_populated_enclosures.xml b/toolkit/components/feeds/test/xml/rss2/item_populated_enclosures.xml
new file mode 100644
index 000000000..0a7d60df6
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_populated_enclosures.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item enclosure is added to enclosures array
+Expect: var encs = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).enclosures; encs.QueryInterface(Components.interfaces.nsIArray); var enc = encs.queryElementAt(0, Components.interfaces.nsIPropertyBag2); ((enc.getProperty('length') == '24986239') && (enc.getProperty('type') == 'audio/mpeg') && (enc.getProperty('url') == 'http://dallas.example.com/joebob_050689.mp3'));
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+
+<enclosure length="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test</title>
+
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_pubDate.xml b/toolkit/components/feeds/test/xml/rss2/item_pubDate.xml
new file mode 100644
index 000000000..acb4abdcc
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_pubDate.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: entry pubDate works
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).published == 'Tue, 02 Sep 2003 00:00:01 GMT'
+
+-->
+<rss version="2.0" xmlns:dcterms="http://purl.org/dc/terms/">
+<channel>
+<item>
+<pubDate>Tue, 02 Sep 2003 00:00:01 GMT</pubDate>
+</item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_published.xml b/toolkit/components/feeds/test/xml/rss2/item_published.xml
new file mode 100644
index 000000000..86bf55602
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_published.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: entry published works
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).published == 'Sat, 07 Sep 2002 00:00:01 GMT'
+
+-->
+<rss version="2.0" xmlns:dcterms="http://purl.org/dc/terms/">
+<channel>
+<item>
+<dcterms:issued>Sat, 07 Sep 2002 00:00:01 GMT</dcterms:issued>
+</item>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/item_title.xml b/toolkit/components/feeds/test/xml/rss2/item_title.xml
new file mode 100644
index 000000000..0126d7da0
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_title.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item title works
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).fields.getProperty('title') == 'test'
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+ <title>test</title>
+</item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_title_normalized.xml b/toolkit/components/feeds/test/xml/rss2/item_title_normalized.xml
new file mode 100644
index 000000000..51de0f7e2
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_title_normalized.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: item title works
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).title.text == 'test'
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+ <title>test</title>
+</item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/item_updated_dcdate.xml b/toolkit/components/feeds/test/xml/rss2/item_updated_dcdate.xml
new file mode 100644
index 000000000..dc20cdbc0
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/item_updated_dcdate.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: channel pubDate works
+Expect: feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).updated == 'Sat, 07 Sep 2002 00:00:01 GMT'
+
+-->
+<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<channel>
+<item>
+<dc:date>Sat, 07 Sep 2002 00:00:01 GMT</dc:date>
+</item>
+</channel>
+</rss> \ No newline at end of file
diff --git a/toolkit/components/feeds/test/xml/rss2/items_2_titles.xml b/toolkit/components/feeds/test/xml/rss2/items_2_titles.xml
new file mode 100644
index 000000000..3a0d1eb67
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/items_2_titles.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: 2 items title works
+Expect: ((feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).title.text == 'test') && (feed.items.queryElementAt(1, Components.interfaces.nsIFeedEntry).title.text == 'test #2'))
+
+-->
+<rss version="2.0" >
+<channel>
+<item>
+ <title>test</title>
+</item>
+<item>
+ <title>test #2</title>
+</item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/mrss_content.xml b/toolkit/components/feeds/test/xml/rss2/mrss_content.xml
new file mode 100644
index 000000000..62a47cdef
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/mrss_content.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: mrss content works
+Expect: var enc = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).fields.getPropertyAsInterface('mediacontent', Components.interfaces.nsIArray).queryElementAt(0, Components.interfaces.nsIPropertyBag); Assert.equal(enc.getProperty('fileSize'), '24986239', 'file size is correct'); Assert.equal(enc.getProperty('type'), 'video/mpeg', 'type is correct'); Assert.equal(enc.getProperty('url'), 'http://dallas.example.com/joebob_050689.mpeg', 'url is correct'); Assert.equal(feed.type, 4, 'Feed type is correct'); Assert.equal(feed.enclosureCount,1, 'Enclosure count is correct'); true;
+
+-->
+<rss xmlns:media="http://search.yahoo.com/mrss" version="2.0" >
+<channel>
+<item>
+
+<media:content fileSize="24986239" type="video/mpeg" url="http://dallas.example.com/joebob_050689.mpeg" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test</title>
+
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/mrss_content2.xml b/toolkit/components/feeds/test/xml/rss2/mrss_content2.xml
new file mode 100644
index 000000000..a0d740e69
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/mrss_content2.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: mrss content with a thumbnail
+Expect: var enc = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).fields.getPropertyAsInterface('mediacontent', Components.interfaces.nsIArray).queryElementAt(0, Components.interfaces.nsIPropertyBag); Assert.equal(enc.getProperty('fileSize'), '24986239', 'file size is correct'); Assert.equal(enc.getProperty('type'), 'video/mpeg', 'type is correct'); Assert.equal(enc.getProperty('url'), 'http://dallas.example.com/joebob_050689.mpeg', 'url is correct'); Assert.equal(feed.type, 0, 'Feed type is correct'); Assert.equal(feed.enclosureCount,2, 'Enclosure count is correct'); true;
+
+-->
+<rss xmlns:media="http://search.yahoo.com/mrss" version="2.0" >
+<channel>
+<item>
+
+<media:content fileSize="24986239" type="video/mpeg" url="http://dallas.example.com/joebob_050689.mpeg" />
+<media:thumbnail url="http://dallas.example.com/joebob_050689.jpg" width="75" height="50"/>
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test</title>
+
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/mrss_content_429049.xml b/toolkit/components/feeds/test/xml/rss2/mrss_content_429049.xml
new file mode 100644
index 000000000..d13efc94c
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/mrss_content_429049.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: this tests bug 429049. the item with a valid url is added to the enclosures array and the item with an empty url does not.
+Expect: var encs = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).enclosures; encs.QueryInterface(Components.interfaces.nsIArray); (encs.length == 1);
+
+-->
+<rss xmlns:media="http://search.yahoo.com/mrss" version="2.0" >
+<channel>
+
+<item>
+<media:content fileSize="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test</title>
+
+<category domain="foo">bar</category>
+<description>no description</description>
+</item>
+
+<item>
+<media:content url="" height="" width=""></media:content>
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test empty</title>
+
+<category domain="foo">bar</category>
+<description>no description</description>
+</item>
+
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/mrss_content_multiple.xml b/toolkit/components/feeds/test/xml/rss2/mrss_content_multiple.xml
new file mode 100644
index 000000000..c391efdd2
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/mrss_content_multiple.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: mrss content with multiple media:content items works
+Expect: var mcs = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).fields.getProperty('mediacontent'); mcs.QueryInterface(Components.interfaces.nsIArray); var enc1 = mcs.queryElementAt(0, Components.interfaces.nsIPropertyBag); var enc2 = mcs.queryElementAt(1, Components.interfaces.nsIPropertyBag); ((enc1.getProperty('fileSize') == '24986239') && (enc1.getProperty('type') == 'video/mpeg') && (enc1.getProperty('url') == 'http://dallas.example.com/joebob_1.mpeg') && (enc2.getProperty('fileSize') == '30000000') && (enc2.getProperty('type') == 'video/mpeg') && (enc2.getProperty('url') == 'http://dallas.example.com/joebob_2.mpeg') && (feed.type == 4) && (feed.enclosureCount == 2));
+
+-->
+<rss xmlns:media="http://search.yahoo.com/mrss" version="2.0" >
+<channel>
+<item>
+
+<media:content fileSize="24986239" type="video/mpeg" url="http://dallas.example.com/joebob_1.mpeg" />
+<media:content fileSize="30000000" type="video/mpeg" url="http://dallas.example.com/joebob_2.mpeg" />
+
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test</title>
+
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while. Two videos of that.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/mrss_content_populate_enclosure.xml b/toolkit/components/feeds/test/xml/rss2/mrss_content_populate_enclosure.xml
new file mode 100644
index 000000000..f0718655f
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/mrss_content_populate_enclosure.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: mrss content added to enclosures array
+Expect: var encs = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).enclosures; encs.QueryInterface(Components.interfaces.nsIArray); var enc = encs.queryElementAt(0, Components.interfaces.nsIPropertyBag); ((enc.getProperty('length') == '24986239') && (enc.getProperty('type') == 'audio/mpeg') && (enc.getProperty('url') == 'http://dallas.example.com/joebob_050689.mp3') && (feed.type == 1) && (feed.enclosureCount == 1));
+
+-->
+<rss xmlns:media="http://search.yahoo.com/mrss" version="2.0" >
+<channel>
+<item>
+
+<media:content fileSize="24986239" type="audio/mpeg" url="http://dallas.example.com/joebob_050689.mp3" />
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test</title>
+
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/mrss_group_content.xml b/toolkit/components/feeds/test/xml/rss2/mrss_group_content.xml
new file mode 100644
index 000000000..da2ddb29c
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/mrss_group_content.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: mrss group content works
+Expect: var mg = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).fields.getProperty('mediagroup'); mg.QueryInterface(Components.interfaces.nsIPropertyBag); var mcs = mg.getProperty("mediacontent"); mcs.QueryInterface(Components.interfaces.nsIArray); var mc1 = mcs.queryElementAt(0, Components.interfaces.nsIPropertyBag); var mc2 = mcs.queryElementAt(1, Components.interfaces.nsIPropertyBag); ((mc1.getProperty('fileSize') == '400') && (mc1.getProperty('type') == 'audio/mpeg') && (mc1.getProperty('url') == 'http://dallas.example.com/joebob_050689_2.mp3') && (mc2.getProperty('fileSize') == '200') && (mc2.getProperty('type') == 'audio/mpeg') && (mc2.getProperty('url') == 'http://dallas.example.com/joebob_050689_1.mp3'));
+
+-->
+<rss xmlns:media="http://search.yahoo.com/mrss" version="2.0" >
+<channel>
+<item>
+
+<media:group>
+ <media:content fileSize="400" type="audio/mpeg" url="http://dallas.example.com/joebob_050689_2.mp3" />
+ <media:content fileSize="200" type="audio/mpeg" url="http://dallas.example.com/joebob_050689_1.mp3" />
+</media:group>
+
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test</title>
+
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xml/rss2/mrss_group_content_populate_enclosure.xml b/toolkit/components/feeds/test/xml/rss2/mrss_group_content_populate_enclosure.xml
new file mode 100644
index 000000000..f7b9ebabf
--- /dev/null
+++ b/toolkit/components/feeds/test/xml/rss2/mrss_group_content_populate_enclosure.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+
+Description: mrss group content works
+Expect: var encs = feed.items.queryElementAt(0, Components.interfaces.nsIFeedEntry).enclosures; encs.QueryInterface(Components.interfaces.nsIArray); var enc1 = encs.queryElementAt(0, Components.interfaces.nsIPropertyBag); var enc2 = encs.queryElementAt(1, Components.interfaces.nsIPropertyBag); ((enc1.getProperty('length') == '400') && (enc1.getProperty('type') == 'audio/mpeg') && (enc1.getProperty('url') == 'http://dallas.example.com/joebob_050689_2.mp3') && (enc2.getProperty('length') == '200') && (enc2.getProperty('type') == 'audio/mpeg') && (enc2.getProperty('url') == 'http://dallas.example.com/joebob_050689_1.mp3'));
+
+
+-->
+<rss xmlns:media="http://search.yahoo.com/mrss" version="2.0" >
+<channel>
+<item>
+
+<media:group>
+ <media:content fileSize="400" type="audio/mpeg" url="http://dallas.example.com/joebob_050689_2.mp3" />
+ <media:content fileSize="200" type="audio/mpeg" url="http://dallas.example.com/joebob_050689_1.mp3" />
+</media:group>
+
+<author>jbb@dallas.example.com (Joe Bob Briggs)</author>
+<comments>http://example.org</comments>
+<title>test</title>
+
+<category domain="foo">bar</category>
+
+<description>I'm headed for France. I wasn't gonna go this year, but then last week &lt;a href="http://www.imdb.com/title/tt0086525/"&gt;Valley Girl&lt;/a&gt; came out and I said to myself, Joe Bob, you gotta get out of the country for a while.</description></item>
+</channel>
+</rss>
diff --git a/toolkit/components/feeds/test/xpcshell.ini b/toolkit/components/feeds/test/xpcshell.ini
new file mode 100644
index 000000000..fbed5e559
--- /dev/null
+++ b/toolkit/components/feeds/test/xpcshell.ini
@@ -0,0 +1,209 @@
+[DEFAULT]
+head = head.js
+tail =
+skip-if = toolkit == 'android'
+support-files =
+ xml/rfc4287/author_namespaces.xml
+ xml/rfc4287/entry_link_IANA.xml
+ xml/rfc4287/feed_author_email_2.xml
+ xml/rfc4287/feed_logo.xml
+ xml/rfc4287/entry_author.xml
+ xml/rfc4287/entry_link_otherURI_alt.xml
+ xml/rfc4287/feed_author_email.xml
+ xml/rfc4287/feed_random_attributes_on_feed_and_entry.xml
+ xml/rfc4287/entry_content_encoded.xml
+ xml/rfc4287/entry_link_payment_alt.xml
+ xml/rfc4287/feed_author_name.xml
+ xml/rfc4287/feed_rights_normalized.xml
+ xml/rfc4287/entry_content_html.xml
+ xml/rfc4287/entry_link_random.xml
+ xml/rfc4287/feed_author_surrounded.xml
+ xml/rfc4287/feed_rights_xhtml_nested_divs.xml
+ xml/rfc4287/entry_content_xhtml_with_markup.xml
+ xml/rfc4287/entry_published.xml
+ xml/rfc4287/feed_author_uri.xml
+ xml/rfc4287/feed_rights_xhtml.xml
+ xml/rfc4287/entry_content_xhtml.xml
+ xml/rfc4287/entry_rights_normalized.xml
+ xml/rfc4287/feed_author.xml
+ xml/rfc4287/feed_subtitle.xml
+ xml/rfc4287/entry_content.xml
+ xml/rfc4287/entry_summary.xml
+ xml/rfc4287/feed_comment_rss_extra_att.xml
+ xml/rfc4287/feed_tantek_title.xml
+ xml/rfc4287/entry_contributor.xml
+ xml/rfc4287/entry_title_normalized.xml
+ xml/rfc4287/feed_contributor.xml
+ xml/rfc4287/feed_title_full_feed.xml
+ xml/rfc4287/entry_html_cdata.xml
+ xml/rfc4287/entry_title.xml
+ xml/rfc4287/feed_entry_count.xml
+ xml/rfc4287/feed_title_xhtml_entities.xml
+ xml/rfc4287/entry_id.xml
+ xml/rfc4287/entry_updated.xml
+ xml/rfc4287/feed_generator_uri.xml
+ xml/rfc4287/feed_title_xhtml.xml
+ xml/rfc4287/entry_link_2alts_allcore2.xml
+ xml/rfc4287/entry_w_content_encoded.xml
+ xml/rfc4287/feed_generator_uri_xmlbase.xml
+ xml/rfc4287/feed_title.xml
+ xml/rfc4287/entry_link_2alts_allcore.xml
+ xml/rfc4287/entry_xhtml_baseURI_with_amp.xml
+ xml/rfc4287/feed_generator_version.xml
+ xml/rfc4287/feed_updated_invalid.xml
+ xml/rfc4287/entry_link_2alts.xml
+ xml/rfc4287/entry_xmlBase_on_link.xml
+ xml/rfc4287/feed_generator.xml
+ xml/rfc4287/feed_updated_normalized.xml
+ xml/rfc4287/entry_link_alt_extension.xml
+ xml/rfc4287/entry_xmlBase.xml
+ xml/rfc4287/feed_icon.xml
+ xml/rfc4287/feed_updated.xml
+ xml/rfc4287/entry_link_enclosure_populate_enclosures.xml
+ xml/rfc4287/feed_atom_rights_xhtml.xml
+ xml/rfc4287/feed_id_extra_att.xml
+ xml/rfc4287/feed_version.xml
+ xml/rfc4287/entry_link_enclosure.xml
+ xml/rfc4287/feed_author2.xml
+ xml/rfc4287/feed_id.xml
+ xml/rfc4287/feed_xmlBase.xml
+ xml/rss09x/rss090.xml
+ xml/rss09x/rss091_withNS.xml
+ xml/rss09x/rss091.xml
+ xml/rss09x/rss092.xml
+ xml/rss09x/rss093.xml
+ xml/rss09x/rss094.xml
+ xml/rss09x/rssUnknown.xml
+ xml/rss1/feed_bogus_title.xml
+ xml/rss1/feed_description_normalized.xml
+ xml/rss1/feed_description_with_dc_only.xml
+ xml/rss1/feed_description_with_dc.xml
+ xml/rss1/feed_description.xml
+ xml/rss1/feed_generator.xml
+ xml/rss1/feed_id.xml
+ xml/rss1/feed_image.xml
+ xml/rss1/feed_items_length_zero.xml
+ xml/rss1/feed_link_normalized.xml
+ xml/rss1/feed_link.xml
+ xml/rss1/feed_textInput.xml
+ xml/rss1/feed_title_extra_att.xml
+ xml/rss1/feed_title_normalized.xml
+ xml/rss1/feed_title.xml
+ xml/rss1/feed_updated_dctermsmodified.xml
+ xml/rss1/feed_updated.xml
+ xml/rss1/feed_version.xml
+ xml/rss1/full_feed_not_bozo.xml
+ xml/rss1/full_feed_unknown_extension.xml
+ xml/rss1/full_feed.xml
+ xml/rss1/item_2_dc_description.xml
+ xml/rss1/item_2_dc_publisher_extra_att_invalid_rdf.xml
+ xml/rss1/item_2_dc_publisher.xml
+ xml/rss1/item_count.xml
+ xml/rss1/item_dc_creator.xml
+ xml/rss1/item_dc_description_normalized.xml
+ xml/rss1/item_dc_description.xml
+ xml/rss1/item_description.xml
+ xml/rss1/item_id.xml
+ xml/rss1/item_link_normalized.xml
+ xml/rss1/item_link.xml
+ xml/rss1/item_title_normalized.xml
+ xml/rss1/item_title.xml
+ xml/rss1/item_updated_dcterms.xml
+ xml/rss1/item_wiki_importance_extra_att.xml
+ xml/rss2/feed_category_count.xml
+ xml/rss2/feed_category.xml
+ xml/rss2/feed_cloud.xml
+ xml/rss2/feed_copyright_linebreak.xml
+ xml/rss2/feed_copyright.xml
+ xml/rss2/feed_data_outside_channel.xml
+ xml/rss2/feed_dc_contributor.xml
+ xml/rss2/feed_dc_creator.xml
+ xml/rss2/feed_description_html_cdata.xml
+ xml/rss2/feed_description_html.xml
+ xml/rss2/feed_description.xml
+ xml/rss2/feed_docs.xml
+ xml/rss2/feed_generator.xml
+ xml/rss2/feed_image_desc_width_height.xml
+ xml/rss2/feed_image_desc.xml
+ xml/rss2/feed_image_required.xml
+ xml/rss2/feed_language.xml
+ xml/rss2/feed_lastBuildDate.xml
+ xml/rss2/feed_linebreak_link.xml
+ xml/rss2/feed_link_cdata.xml
+ xml/rss2/feed_link.xml
+ xml/rss2/feed_managingEditor_extra_att.xml
+ xml/rss2/feed_managingEditor.xml
+ xml/rss2/feed_multiple_categories.xml
+ xml/rss2/feed_pubDate_invalid.xml
+ xml/rss2/feed_pubDate_nonRFC822_1.xml
+ xml/rss2/feed_pubDate_nonRFC822_2.xml
+ xml/rss2/feed_pubDate_timezoneZ.xml
+ xml/rss2/feed_pubDate_utc.xml
+ xml/rss2/feed_pubDate.xml
+ xml/rss2/feed_rating.xml
+ xml/rss2/feed_single_quote_stylesheet_pi.xml
+ xml/rss2/feed_skipDays.xml
+ xml/rss2/feed_skipHours.xml
+ xml/rss2/feed_subtitle_html.xml
+ xml/rss2/feed_subtitle_markup_stripped.xml
+ xml/rss2/feed_subtitle.xml
+ xml/rss2/feed_textinput.xml
+ xml/rss2/feed_title_cdata_mixed.xml
+ xml/rss2/feed_title_nesting.xml
+ xml/rss2/feed_title.xml
+ xml/rss2/feed_ttl.xml
+ xml/rss2/feed_updated_dcdate.xml
+ xml/rss2/feed_updated_lastBuildDate_priority.xml
+ xml/rss2/feed_updated_lastBuildDate.xml
+ xml/rss2/feed_updated.xml
+ xml/rss2/feed_webMaster.xml
+ xml/rss2/feed_wfw_commentapi.xml
+ xml/rss2/feed_wfw_commentrss.xml
+ xml/rss2/feed_wiki_unusual_prefix.xml
+ xml/rss2/feed_wiki.xml
+ xml/rss2/item_author.xml
+ xml/rss2/item_category.xml
+ xml/rss2/item_comments.xml
+ xml/rss2/item_content_encoded.xml
+ xml/rss2/item_count2.xml
+ xml/rss2/item_count.xml
+ xml/rss2/item_description_2.xml
+ xml/rss2/item_description_cdata.xml
+ xml/rss2/item_description_decode_entities.xml
+ xml/rss2/item_description_normalized_nohtml.xml
+ xml/rss2/item_description_normalized.xml
+ xml/rss2/item_description.xml
+ xml/rss2/item_enclosure_duplicates2.xml
+ xml/rss2/item_enclosure_duplicates.xml
+ xml/rss2/item_enclosure_mixed2.xml
+ xml/rss2/item_enclosure_mixed.xml
+ xml/rss2/item_enclosure.xml
+ xml/rss2/item_guid_bogus_url.xml
+ xml/rss2/item_guid_isPermaLink_default.xml
+ xml/rss2/item_guid_isPermaLink_false_uppercase.xml
+ xml/rss2/item_guid_isPermaLink_false.xml
+ xml/rss2/item_guid_isPermaLink_true_uppercase.xml
+ xml/rss2/item_guid_isPermaLink_unknown_value.xml
+ xml/rss2/item_guid_isPermaLink.xml
+ xml/rss2/item_guid_normalized.xml
+ xml/rss2/item_guid_with_link.xml
+ xml/rss2/item_guid.xml
+ xml/rss2/item_link_normalized.xml
+ xml/rss2/item_link.xml
+ xml/rss2/item_plain_desc.xml
+ xml/rss2/item_populated_enclosures.xml
+ xml/rss2/item_pubDate.xml
+ xml/rss2/item_published.xml
+ xml/rss2/items_2_titles.xml
+ xml/rss2/item_title_normalized.xml
+ xml/rss2/item_title.xml
+ xml/rss2/item_updated_dcdate.xml
+ xml/rss2/mrss_content_429049.xml
+ xml/rss2/mrss_content_multiple.xml
+ xml/rss2/mrss_content_populate_enclosure.xml
+ xml/rss2/mrss_content.xml
+ xml/rss2/mrss_content2.xml
+ xml/rss2/mrss_group_content_populate_enclosure.xml
+ xml/rss2/mrss_group_content.xml
+
+[test_xml.js]