Bug 1134507 - Implement infopanel to promote Reader View when first available. r=Gijs, a=sledru
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Thu, 30 Apr 2015 14:24:00 -0400
changeset 260404 f53c601dafa3
parent 260403 8cba8416a229
child 260405 810e81a9bced
push id771
push userryanvm@gmail.com
push date2015-05-05 02:31 +0000
treeherdermozilla-release@810e81a9bced [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs, sledru
bugs1134507
milestone38.0
Bug 1134507 - Implement infopanel to promote Reader View when first available. r=Gijs, a=sledru Based on a patch by Jared Wein (:jaws).
browser/app/profile/firefox.js
browser/base/content/test/general/browser_readerMode.js
browser/components/uitour/UITour.jsm
browser/modules/ReaderParent.jsm
browser/themes/linux/jar.mn
browser/themes/osx/jar.mn
browser/themes/shared/reader/reader-tour.png
browser/themes/shared/reader/reader-tour@2x.png
browser/themes/windows/jar.mn
testing/profiles/prefs_general.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1891,10 +1891,11 @@ pref("dom.ipc.reportProcessHangs", false
 pref("dom.ipc.reportProcessHangs", true);
 #endif
 
 pref("browser.readinglist.enabled", false);
 pref("browser.readinglist.sidebarEverOpened", false);
 pref("readinglist.scheduler.enabled", false);
 pref("readinglist.server", "https://readinglist.services.mozilla.com/v1");
 
+pref("browser.reader.detectedFirstArticle", false);
 // Don't limit how many nodes we care about on desktop:
 pref("reader.parse-node-limit", 0);
--- a/browser/base/content/test/general/browser_readerMode.js
+++ b/browser/base/content/test/general/browser_readerMode.js
@@ -27,29 +27,39 @@ add_task(function* test_reader_button() 
       gBrowser.removeCurrentTab();
     }
   });
 
   // Set required test prefs.
   TEST_PREFS.forEach(([name, value]) => {
     Services.prefs.setBoolPref(name, value);
   });
+  Services.prefs.setBoolPref("browser.reader.detectedFirstArticle", false);
 
   let tab = gBrowser.selectedTab = gBrowser.addTab();
   is_element_hidden(readerButton, "Reader mode button is not present on a new tab");
+  ok(!UITour.isInfoOnTarget(window, "readerMode-urlBar"),
+     "Info panel shouldn't appear without the reader mode button");
+  ok(!Services.prefs.getBoolPref("browser.reader.detectedFirstArticle"),
+     "Shouldn't have detected the first article");
 
   // Point tab to a test page that is reader-able.
   let url = TEST_PATH + "readerModeArticle.html";
   yield promiseTabLoadEvent(tab, url);
   yield promiseWaitForCondition(() => !readerButton.hidden);
   is_element_visible(readerButton, "Reader mode button is present on a reader-able page");
+  ok(UITour.isInfoOnTarget(window, "readerMode-urlBar"),
+     "Info panel should be anchored at the reader mode button");
+  ok(Services.prefs.getBoolPref("browser.reader.detectedFirstArticle"),
+     "Should have detected the first article");
 
   // Switch page into reader mode.
   readerButton.click();
   yield promiseTabLoadEvent(tab);
+  ok(!UITour.isInfoOnTarget(window, "readerMode-urlBar"), "Info panel should have closed");
 
   let readerUrl = gBrowser.selectedBrowser.currentURI.spec;
   ok(readerUrl.startsWith("about:reader"), "about:reader loaded after clicking reader mode button");
   is_element_visible(readerButton, "Reader mode button is present on about:reader");
 
   is(gURLBar.value, readerUrl, "gURLBar value is about:reader URL");
   is(gURLBar.textValue, url.substring("http://".length), "gURLBar is displaying original article URL");
 
--- a/browser/components/uitour/UITour.jsm
+++ b/browser/components/uitour/UITour.jsm
@@ -1455,16 +1455,22 @@ this.UITour = {
     if (aAnchor.targetName.startsWith(TARGET_SEARCHENGINE_PREFIX))
       return;
 
     this._setAppMenuStateForAnnotation(aChromeWindow, "info",
                                        this.targetIsInAppMenu(aAnchor),
                                        showInfoPanel.bind(this, this._correctAnchor(aAnchor.node)));
   },
 
+  isInfoOnTarget(aChromeWindow, aTargetName) {
+    let document = aChromeWindow.document;
+    let tooltip = document.getElementById("UITourTooltip");
+    return tooltip.getAttribute("targetName") == aTargetName && tooltip.state != "closed";
+  },
+
   hideInfo: function(aWindow) {
     let document = aWindow.document;
 
     let tooltip = document.getElementById("UITourTooltip");
     this._removeAnnotationPanelMutationObserver(tooltip);
     tooltip.hidePopup();
     this._setAppMenuStateForAnnotation(aWindow, "info", false);
 
--- a/browser/modules/ReaderParent.jsm
+++ b/browser/modules/ReaderParent.jsm
@@ -16,16 +16,17 @@ Cu.import("resource://gre/modules/Task.j
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils","resource://gre/modules/PlacesUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ReaderMode", "resource://gre/modules/ReaderMode.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ReadingList", "resource:///modules/readinglist/ReadingList.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "UITour", "resource:///modules/UITour.jsm");
 
 const gStringBundle = Services.strings.createBundle("chrome://global/locale/aboutReader.properties");
 
 let ReaderParent = {
+  _readerModeInfoPanelOpen: false,
 
   MESSAGES: [
     "Reader:AddToList",
     "Reader:ArticleGet",
     "Reader:FaviconRequest",
     "Reader:ListStatusRequest",
     "Reader:RemoveFromList",
     "Reader:Share",
@@ -151,16 +152,30 @@ let ReaderParent = {
     } else {
       button.removeAttribute("readeractive");
       button.hidden = !browser.isArticle;
       let enterText = gStringBundle.GetStringFromName("readerView.enter");
       button.setAttribute("tooltiptext", enterText);
       command.setAttribute("label", enterText);
       command.setAttribute("hidden", !browser.isArticle);
     }
+
+    let currentUriHost = browser.currentURI && browser.currentURI.asciiHost;
+    if (browser.isArticle &&
+        !Services.prefs.getBoolPref("browser.reader.detectedFirstArticle") &&
+        currentUriHost && !currentUriHost.endsWith("mozilla.org")) {
+      this.showReaderModeInfoPanel(browser);
+      Services.prefs.setBoolPref("browser.reader.detectedFirstArticle", true);
+      this._readerModeInfoPanelOpen = true;
+    } else if (this._readerModeInfoPanelOpen) {
+      if (UITour.isInfoOnTarget(win, "readerMode-urlBar")) {
+        UITour.hideInfo(win);
+      }
+      this._readerModeInfoPanelOpen = false;
+    }
   },
 
   buttonClick: function(event) {
     if (event.button != 0) {
       return;
     }
     this.toggleReaderMode(event);
   },
@@ -187,20 +202,26 @@ let ReaderParent = {
    *
    * @param browser The <browser> that the tour should be started for.
    */
   showReaderModeInfoPanel(browser) {
     let win = browser.ownerDocument.defaultView;
     let targetPromise = UITour.getTarget(win, "readerMode-urlBar");
     targetPromise.then(target => {
       let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
+      let icon = "chrome://browser/skin/";
+      if (win.devicePixelRatio > 1) {
+        icon += "reader-tour@2x.png";
+      } else {
+        icon += "reader-tour.png";
+      }
       UITour.showInfo(win, browser.messageManager, target,
-                      browserBundle.GetStringFromName("readerView.promo.firstDetectedArticle.title"),
-                      browserBundle.GetStringFromName("readerView.promo.firstDetectedArticle.body"),
-                      "chrome://browser/skin/reader-tour.png");
+                      browserBundle.GetStringFromName("readingList.promo.firstUse.readerView.title"),
+                      browserBundle.GetStringFromName("readingList.promo.firstUse.readerView.body"),
+                      icon);
     });
   },
 
   /**
    * Gets an article for a given URL. This method will download and parse a document.
    *
    * @param url The article URL.
    * @param browser The browser where the article is currently loaded.
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -87,16 +87,17 @@ browser.jar:
   skin/classic/browser/Toolbar-small.png
   skin/classic/browser/undoCloseTab.png                        (../shared/undoCloseTab.png)
   skin/classic/browser/update-badge.svg                        (../shared/update-badge.svg)
   skin/classic/browser/urlbar-arrow.png
   skin/classic/browser/session-restore.svg                  (../shared/incontent-icons/session-restore.svg)
   skin/classic/browser/tab-crashed.svg                      (../shared/incontent-icons/tab-crashed.svg)
   skin/classic/browser/welcome-back.svg                     (../shared/incontent-icons/welcome-back.svg)
   skin/classic/browser/reader-tour.png                      (../shared/reader/reader-tour.png)
+  skin/classic/browser/reader-tour@2x.png                   (../shared/reader/reader-tour@2x.png)
   skin/classic/browser/readerMode.svg                       (../shared/reader/readerMode.svg)
   skin/classic/browser/readinglist/icons.svg          (../shared/readinglist/icons.svg)
   skin/classic/browser/readinglist/readinglist-icon.svg (../shared/readinglist/readinglist-icon.svg)
 * skin/classic/browser/readinglist/sidebar.css        (readinglist/sidebar.css)
   skin/classic/browser/webRTC-shareDevice-16.png
   skin/classic/browser/webRTC-shareDevice-64.png
   skin/classic/browser/webRTC-sharingDevice-16.png    (../shared/webrtc/webRTC-sharingDevice-16.png)
   skin/classic/browser/webRTC-shareMicrophone-16.png
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -137,16 +137,17 @@ browser.jar:
   skin/classic/browser/urlbar-arrow.png
   skin/classic/browser/urlbar-arrow@2x.png
   skin/classic/browser/urlbar-popup-blocked.png
   skin/classic/browser/urlbar-popup-blocked@2x.png
   skin/classic/browser/session-restore.svg            (../shared/incontent-icons/session-restore.svg)
   skin/classic/browser/tab-crashed.svg                (../shared/incontent-icons/tab-crashed.svg)
   skin/classic/browser/welcome-back.svg               (../shared/incontent-icons/welcome-back.svg)
   skin/classic/browser/reader-tour.png                (../shared/reader/reader-tour.png)
+  skin/classic/browser/reader-tour@2x.png             (../shared/reader/reader-tour@2x.png)
   skin/classic/browser/readerMode.svg                 (../shared/reader/readerMode.svg)
   skin/classic/browser/readinglist/icons.svg          (../shared/readinglist/icons.svg)
   skin/classic/browser/readinglist/readinglist-icon.svg (../shared/readinglist/readinglist-icon.svg)
 * skin/classic/browser/readinglist/sidebar.css        (readinglist/sidebar.css)
   skin/classic/browser/webRTC-shareDevice-16.png
   skin/classic/browser/webRTC-shareDevice-16@2x.png
   skin/classic/browser/webRTC-shareDevice-64.png
   skin/classic/browser/webRTC-shareDevice-64@2x.png
index 8e557e03821219211c19f65a90ca03d2f0b3b03f..be346b3847928f94d7a0bbca019f40d86edd0899
GIT binary patch
literal 2672
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1a60d93ca9311f8bf9e0ce3f6f175370a69f648e
GIT binary patch
literal 6426
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
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -106,16 +106,17 @@ browser.jar:
         skin/classic/browser/update-badge.svg                        (../shared/update-badge.svg)
         skin/classic/browser/urlbar-arrow.png
         skin/classic/browser/urlbar-popup-blocked.png
         skin/classic/browser/urlbar-history-dropmarker.png
         skin/classic/browser/session-restore.svg                     (../shared/incontent-icons/session-restore.svg)
         skin/classic/browser/tab-crashed.svg                         (../shared/incontent-icons/tab-crashed.svg)
         skin/classic/browser/welcome-back.svg                        (../shared/incontent-icons/welcome-back.svg)
         skin/classic/browser/reader-tour.png                         (../shared/reader/reader-tour.png)
+        skin/classic/browser/reader-tour@2x.png                      (../shared/reader/reader-tour@2x.png)
         skin/classic/browser/readerMode.svg                          (../shared/reader/readerMode.svg)
         skin/classic/browser/readinglist/icons.svg                   (../shared/readinglist/icons.svg)
         skin/classic/browser/readinglist/readinglist-icon.svg        (../shared/readinglist/readinglist-icon.svg)
 *       skin/classic/browser/readinglist/sidebar.css                 (readinglist/sidebar.css)
         skin/classic/browser/notification-pluginNormal.png           (../shared/plugins/notification-pluginNormal.png)
         skin/classic/browser/notification-pluginAlert.png            (../shared/plugins/notification-pluginAlert.png)
         skin/classic/browser/notification-pluginBlocked.png          (../shared/plugins/notification-pluginBlocked.png)
         skin/classic/browser/webRTC-shareDevice-16.png
@@ -575,16 +576,18 @@ browser.jar:
         skin/classic/aero/browser/undoCloseTab@2x.png                     (../shared/undoCloseTab@2x.png)
         skin/classic/aero/browser/update-badge.svg                        (../shared/update-badge.svg)
         skin/classic/aero/browser/urlbar-arrow.png
         skin/classic/aero/browser/urlbar-popup-blocked.png
         skin/classic/aero/browser/urlbar-history-dropmarker.png
         skin/classic/aero/browser/session-restore.svg               (../shared/incontent-icons/session-restore.svg)
         skin/classic/aero/browser/tab-crashed.svg                   (../shared/incontent-icons/tab-crashed.svg)
         skin/classic/aero/browser/welcome-back.svg                  (../shared/incontent-icons/welcome-back.svg)
+        skin/classic/aero/browser/reader-tour.png                   (../shared/reader/reader-tour.png)
+        skin/classic/aero/browser/reader-tour@2x.png                (../shared/reader/reader-tour@2x.png)
         skin/classic/aero/browser/readerMode.svg                    (../shared/reader/readerMode.svg)
         skin/classic/aero/browser/readinglist/icons.svg             (../shared/readinglist/icons.svg)
         skin/classic/aero/browser/readinglist/readinglist-icon.svg  (../shared/readinglist/readinglist-icon.svg)
 *       skin/classic/aero/browser/readinglist/sidebar.css           (readinglist/sidebar.css)
         skin/classic/aero/browser/notification-pluginNormal.png     (../shared/plugins/notification-pluginNormal.png)
         skin/classic/aero/browser/notification-pluginAlert.png      (../shared/plugins/notification-pluginAlert.png)
         skin/classic/aero/browser/notification-pluginBlocked.png    (../shared/plugins/notification-pluginBlocked.png)
         skin/classic/aero/browser/webRTC-shareDevice-16.png
--- a/testing/profiles/prefs_general.js
+++ b/testing/profiles/prefs_general.js
@@ -293,10 +293,11 @@ user_pref("media.decoder.heuristic.dorma
 
 // Don't prompt about e10s
 user_pref("browser.displayedE10SPrompt.1", 5);
 // Don't use auto-enabled e10s
 user_pref("browser.tabs.remote.autostart.1", false);
 // Don't forceably kill content processes after a timeout
 user_pref("dom.ipc.tabs.shutdownTimeoutSecs", 0);
 
-// Avoid performing Readinglist Intro during tests.
+// Avoid performing Reading List and Reader Mode intros during tests.
 user_pref("browser.readinglist.introShown", true);
+user_pref("browser.reader.detectedFirstArticle", true);