Bug 1241810 - Add support for wordpress.com. r=mcomella draft
authorSebastian Kaspari <s.kaspari@gmail.com>
Fri, 26 Feb 2016 08:59:51 -0800
changeset 343938 831bf1346e52356385a96b59755b7fd0d10591a3
parent 343937 187ea0285c49fb5fe23a37711bb0a6e951621df8
child 343939 ff5ce6412b88c8744e962e2b17aa0f4143e7dd27
push id13713
push users.kaspari@gmail.com
push dateWed, 23 Mar 2016 15:10:41 +0000
reviewersmcomella
bugs1241810
milestone48.0a1
Bug 1241810 - Add support for wordpress.com. r=mcomella MozReview-Commit-ID: AhXTAFszx6F
mobile/android/base/java/org/mozilla/gecko/feeds/action/EnrollAction.java
mobile/android/base/java/org/mozilla/gecko/feeds/action/SubscribeAction.java
mobile/android/base/java/org/mozilla/gecko/feeds/knownsites/KnownSiteMedium.java
mobile/android/base/java/org/mozilla/gecko/feeds/knownsites/KnownSiteWordpress.java
mobile/android/base/java/org/mozilla/gecko/feeds/parser/SimpleFeedParser.java
mobile/android/base/moz.build
mobile/android/tests/background/junit4/resources/feed_rss_wordpress.xml
mobile/android/tests/background/junit4/src/org/mozilla/gecko/feeds/parser/TestSimpleFeedParser.java
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/action/EnrollAction.java
+++ b/mobile/android/base/java/org/mozilla/gecko/feeds/action/EnrollAction.java
@@ -13,26 +13,28 @@ import android.util.Log;
 
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.feeds.FeedService;
 import org.mozilla.gecko.feeds.knownsites.KnownSiteBlogger;
 import org.mozilla.gecko.feeds.knownsites.KnownSite;
 import org.mozilla.gecko.feeds.knownsites.KnownSiteMedium;
+import org.mozilla.gecko.feeds.knownsites.KnownSiteWordpress;
 
 /**
  * EnrollAction: Search for bookmarks of known sites we can subscribe to.
  */
 public class EnrollAction implements BaseAction {
     private static final String LOGTAG = "FeedEnrollAction";
 
     private static final KnownSite[] knownSites = {
         new KnownSiteMedium(),
         new KnownSiteBlogger(),
+        new KnownSiteWordpress(),
     };
 
     private Context context;
 
     public EnrollAction(Context context) {
         this.context = context;
     }
 
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/action/SubscribeAction.java
+++ b/mobile/android/base/java/org/mozilla/gecko/feeds/action/SubscribeAction.java
@@ -27,29 +27,29 @@ public class SubscribeAction implements 
     private SubscriptionStorage storage;
 
     public SubscribeAction(SubscriptionStorage storage) {
         this.storage = storage;
     }
 
     @Override
     public void perform(Intent intent) {
-        Log.d(LOGTAG, "Subscribing to feed..");
-
         final Bundle extras = intent.getExtras();
 
         // TODO: Using a random UUID as fallback just so that I can subscribe for things that are not bookmarks (testing)
         final String guid = extras.getString(EXTRA_GUID, UUID.randomUUID().toString());
         final String feedUrl = intent.getStringExtra(EXTRA_FEED_URL);
 
         if (storage.hasSubscriptionForBookmark(guid)) {
             Log.d(LOGTAG, "Already subscribed to " + feedUrl + ". Skipping.");
             return;
         }
 
+        Log.d(LOGTAG, "Subscribing to feed: " + feedUrl);
+
         subscribe(guid, feedUrl);
     }
 
     @Override
     public boolean requiresNetwork() {
         return true;
     }
 
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/knownsites/KnownSiteMedium.java
+++ b/mobile/android/base/java/org/mozilla/gecko/feeds/knownsites/KnownSiteMedium.java
@@ -9,17 +9,17 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 /**
  * Medium.com
  */
 public class KnownSiteMedium implements KnownSite {
     @Override
     public String getURLSearchString() {
-        return "medium.com";
+        return "://medium.com/";
     }
 
     @Override
     public String getFeedFromURL(String url) {
         Pattern pattern = Pattern.compile("https?://medium.com/([^/]+)(/.*)?");
         Matcher matcher = pattern.matcher(url);
         if (matcher.matches()) {
             return String.format("https://medium.com/feed/%s", matcher.group(1));
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/feeds/knownsites/KnownSiteWordpress.java
@@ -0,0 +1,26 @@
+package org.mozilla.gecko.feeds.knownsites;
+
+import android.support.annotation.NonNull;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Wordpress.com
+ */
+public class KnownSiteWordpress implements KnownSite {
+    @Override
+    public String getURLSearchString() {
+        return ".wordpress.com";
+    }
+
+    @Override
+    public String getFeedFromURL(String url) {
+        Pattern pattern = Pattern.compile("https?://(.*?).wordpress.com(/.*)?");
+        Matcher matcher = pattern.matcher(url);
+        if (matcher.matches()) {
+            return "https://" + matcher.group(1) + ".wordpress.com/feed/";
+        }
+        return null;
+    }
+}
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/parser/SimpleFeedParser.java
+++ b/mobile/android/base/java/org/mozilla/gecko/feeds/parser/SimpleFeedParser.java
@@ -51,24 +51,26 @@ public class SimpleFeedParser {
     private static final String TAG_ITEM = "item";
     private static final String TAG_LINK = "link";
     private static final String TAG_ENTRY = "entry";
     private static final String TAG_PUBDATE = "pubDate";
     private static final String TAG_UPDATED = "updated";
     private static final String TAG_DATE = "date";
     private static final String TAG_SOURCE = "source";
     private static final String TAG_IMAGE = "image";
+    private static final String TAG_CONTENT = "content";
 
     private class ParserState {
         public Feed feed;
         public Item currentItem;
         public boolean isRSS;
         public boolean isATOM;
         public boolean inSource;
         public boolean inImage;
+        public boolean inContent;
     }
 
     public Feed parse(InputStream in) throws ParserException, IOException {
         final ParserState state = new ParserState();
 
         try {
             final XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
             factory.setNamespaceAware(true);
@@ -152,16 +154,20 @@ public class SimpleFeedParser {
 
             case TAG_SOURCE:
                 state.inSource = true;
                 break;
 
             case TAG_IMAGE:
                 state.inImage = true;
                 break;
+
+            case TAG_CONTENT:
+                state.inContent = true;
+                break;
         }
     }
 
     private void handleEndTag(XmlPullParser parser, ParserState state) {
         switch (parser.getName()) {
             case TAG_ITEM:
             case TAG_ENTRY:
                 handleItemOrEntryREndTag(state);
@@ -169,22 +175,26 @@ public class SimpleFeedParser {
 
             case TAG_SOURCE:
                 state.inSource = false;
                 break;
 
             case TAG_IMAGE:
                 state.inImage = false;
                 break;
+
+            case TAG_CONTENT:
+                state.inContent = false;
+                break;
         }
     }
 
     private void handleTitleStartTag(XmlPullParser parser, ParserState state) throws IOException, XmlPullParserException {
-        if (state.inSource || state.inImage) {
-            // We do not care about titles in <source> or <image> tags.
+        if (state.inSource || state.inImage || state.inContent) {
+            // We do not care about titles in <source>, <image> or <media> tags.
             return;
         }
 
         String title = getTextUntilEndTag(parser, TAG_TITLE);
 
         title = title.replaceAll("[\r\n]", " ");
         title = title.replaceAll("  +", " ");
 
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -281,16 +281,17 @@ gbjar.sources += ['java/org/mozilla/geck
     'feeds/action/SubscribeAction.java',
     'feeds/action/WithdrawAction.java',
     'feeds/FeedAlarmReceiver.java',
     'feeds/FeedFetcher.java',
     'feeds/FeedService.java',
     'feeds/knownsites/KnownSite.java',
     'feeds/knownsites/KnownSiteBlogger.java',
     'feeds/knownsites/KnownSiteMedium.java',
+    'feeds/knownsites/KnownSiteWordpress.java',
     'feeds/parser/Feed.java',
     'feeds/parser/Item.java',
     'feeds/parser/SimpleFeedParser.java',
     'feeds/subscriptions/FeedSubscription.java',
     'feeds/subscriptions/SubscriptionStorage.java',
     'FilePicker.java',
     'FilePickerResultHandler.java',
     'FindInPageBar.java',
new file mode 100644
--- /dev/null
+++ b/mobile/android/tests/background/junit4/resources/feed_rss_wordpress.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
+    xmlns:content="http://purl.org/rss/1.0/modules/content/"
+    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
+    xmlns:dc="http://purl.org/dc/elements/1.1/"
+    xmlns:atom="http://www.w3.org/2005/Atom"
+    xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
+    xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
+    xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
+    >
+
+    <channel>
+        <title>justasimpletest2016</title>
+        <atom:link href="https://justasimpletest2016.wordpress.com/feed/" rel="self" type="application/rss+xml" />
+        <link>https://justasimpletest2016.wordpress.com</link>
+        <description></description>
+        <lastBuildDate>Fri, 26 Feb 2016 22:08:00 +0000</lastBuildDate>
+        <language>en</language>
+        <sy:updatePeriod>hourly</sy:updatePeriod>
+        <sy:updateFrequency>1</sy:updateFrequency>
+        <generator>http://wordpress.com/</generator>
+        <cloud domain='justasimpletest2016.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
+        <image>
+            <url>https://s2.wp.com/i/buttonw-com.png</url>
+            <title>justasimpletest2016</title>
+            <link>https://justasimpletest2016.wordpress.com</link>
+        </image>
+        <atom:link rel="search" type="application/opensearchdescription+xml" href="https://justasimpletest2016.wordpress.com/osd.xml" title="justasimpletest2016" />
+        <atom:link rel='hub' href='https://justasimpletest2016.wordpress.com/?pushpress=hub'/>
+        <item>
+            <title>Hello World!</title>
+            <link>https://justasimpletest2016.wordpress.com/2016/02/26/hello-world/</link>
+            <comments>https://justasimpletest2016.wordpress.com/2016/02/26/hello-world/#respond</comments>
+            <pubDate>Fri, 26 Feb 2016 22:07:46 +0000</pubDate>
+            <dc:creator><![CDATA[justasimpletest2016]]></dc:creator>
+            <category><![CDATA[Uncategorized]]></category>
+
+            <guid isPermaLink="false">http://justasimpletest2016.wordpress.com/?p=6</guid>
+            <description><![CDATA[What&#8217;s up?<img alt="" border="0" src="https://pixel.wp.com/b.gif?host=justasimpletest2016.wordpress.com&#038;blog=107552275&#038;post=6&#038;subd=justasimpletest2016&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
+            <content:encoded><![CDATA[<p>What&#8217;s up?</p><br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/justasimpletest2016.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/justasimpletest2016.wordpress.com/6/" /></a> <img alt="" border="0" src="https://pixel.wp.com/b.gif?host=justasimpletest2016.wordpress.com&#038;blog=107552275&#038;post=6&#038;subd=justasimpletest2016&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
+            <wfw:commentRss>https://justasimpletest2016.wordpress.com/2016/02/26/hello-world/feed/</wfw:commentRss>
+            <slash:comments>0</slash:comments>
+
+            <media:content url="https://2.gravatar.com/avatar/ba82024e6f43884f4ae0e379273b0743?s=96&#38;d=identicon&#38;r=G" medium="image">
+                <media:title type="html">justasimpletest2016</media:title>
+            </media:content>
+        </item>
+        <item>
+            <title>The second post</title>
+            <link>https://justasimpletest2016.wordpress.com/2016/02/26/the-second-post/</link>
+            <comments>https://justasimpletest2016.wordpress.com/2016/02/26/the-second-post/#respond</comments>
+            <pubDate>Fri, 26 Feb 2016 00:23:04 +0000</pubDate>
+            <dc:creator><![CDATA[justasimpletest2016]]></dc:creator>
+            <category><![CDATA[Uncategorized]]></category>
+
+            <guid isPermaLink="false">http://justasimpletest2016.wordpress.com/2016/02/26/the-second-post/</guid>
+            <description><![CDATA[Hello.<img alt="" border="0" src="https://pixel.wp.com/b.gif?host=justasimpletest2016.wordpress.com&#038;blog=107552275&#038;post=4&#038;subd=justasimpletest2016&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
+            <content:encoded><![CDATA[<p>Hello.</p><br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/justasimpletest2016.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/justasimpletest2016.wordpress.com/4/" /></a> <img alt="" border="0" src="https://pixel.wp.com/b.gif?host=justasimpletest2016.wordpress.com&#038;blog=107552275&#038;post=4&#038;subd=justasimpletest2016&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
+            <wfw:commentRss>https://justasimpletest2016.wordpress.com/2016/02/26/the-second-post/feed/</wfw:commentRss>
+            <slash:comments>0</slash:comments>
+
+            <media:content url="https://2.gravatar.com/avatar/ba82024e6f43884f4ae0e379273b0743?s=96&#38;d=identicon&#38;r=G" medium="image">
+                <media:title type="html">justasimpletest2016</media:title>
+            </media:content>
+        </item>
+        <item>
+            <title>This is just a test</title>
+            <link>https://justasimpletest2016.wordpress.com/2016/02/26/this-is-just-a-test/</link>
+            <comments>https://justasimpletest2016.wordpress.com/2016/02/26/this-is-just-a-test/#respond</comments>
+            <pubDate>Fri, 26 Feb 2016 00:22:58 +0000</pubDate>
+            <dc:creator><![CDATA[justasimpletest2016]]></dc:creator>
+            <category><![CDATA[Uncategorized]]></category>
+
+            <guid isPermaLink="false">http://justasimpletest2016.wordpress.com/?p=2</guid>
+            <description><![CDATA[Hello World. First blog post from WordPress.<img alt="" border="0" src="https://pixel.wp.com/b.gif?host=justasimpletest2016.wordpress.com&#038;blog=107552275&#038;post=2&#038;subd=justasimpletest2016&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
+            <content:encoded><![CDATA[<p>Hello World. First blog post from WordPress.</p><br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/justasimpletest2016.wordpress.com/2/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/justasimpletest2016.wordpress.com/2/" /></a> <img alt="" border="0" src="https://pixel.wp.com/b.gif?host=justasimpletest2016.wordpress.com&#038;blog=107552275&#038;post=2&#038;subd=justasimpletest2016&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
+            <wfw:commentRss>https://justasimpletest2016.wordpress.com/2016/02/26/this-is-just-a-test/feed/</wfw:commentRss>
+            <slash:comments>0</slash:comments>
+
+            <media:content url="https://2.gravatar.com/avatar/ba82024e6f43884f4ae0e379273b0743?s=96&#38;d=identicon&#38;r=G" medium="image">
+                <media:title type="html">justasimpletest2016</media:title>
+            </media:content>
+        </item>
+    </channel>
+</rss>
--- a/mobile/android/tests/background/junit4/src/org/mozilla/gecko/feeds/parser/TestSimpleFeedParser.java
+++ b/mobile/android/tests/background/junit4/src/org/mozilla/gecko/feeds/parser/TestSimpleFeedParser.java
@@ -260,16 +260,37 @@ public class TestSimpleFeedParser {
         Item item = feed.getLastItem();
 
         Assert.assertNotNull(item);
         Assert.assertEquals("Google: “Dramatische Verbesserungen” für Chrome in iOS", item.getTitle());
         Assert.assertEquals("http://www.heise.de/newsticker/meldung/Google-Dramatische-Verbesserungen-fuer-Chrome-in-iOS-3085808.html?wt_mc=rss.ho.beitrag.atom", item.getURL());
         Assert.assertEquals(1453915920000L, item.getTimestamp());
     }
 
+    @Test
+    public void testWordpressFeed() throws Exception {
+        InputStream stream = openFeed("feed_rss_wordpress.xml");
+
+        SimpleFeedParser parser = new SimpleFeedParser();
+        Feed feed = parser.parse(stream);
+
+        Assert.assertNotNull(feed);
+        Assert.assertEquals("justasimpletest2016", feed.getTitle());
+        Assert.assertEquals("https://justasimpletest2016.wordpress.com", feed.getWebsiteURL());
+        Assert.assertEquals("https://justasimpletest2016.wordpress.com/feed/", feed.getFeedURL());
+        Assert.assertTrue(feed.isSufficientlyComplete());
+
+        Item item = feed.getLastItem();
+
+        Assert.assertNotNull(item);
+        Assert.assertEquals("Hello World!", item.getTitle());
+        Assert.assertEquals("https://justasimpletest2016.wordpress.com/2016/02/26/hello-world/", item.getURL());
+        Assert.assertEquals(1456524466000L, item.getTimestamp());
+    }
+
     private InputStream openFeed(String fileName) throws URISyntaxException, FileNotFoundException, UnsupportedEncodingException {
         URL url = getClass().getResource("/" + fileName);
         if (url == null) {
             throw new FileNotFoundException(fileName);
         }
 
         return new BufferedInputStream(new FileInputStream(url.getPath()));
     }