Bug 1134507 - Implement infopanel to promote Reader View when first available. r=jaws/Gijs
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Thu, 30 Apr 2015 13:43:47 -0700
changeset 273229 6404e6d64787f793aed2a388c08bdfc9ed43421b
parent 273228 2e1d5dc5393f8a273efc48523fc81eaac3b16ef8
child 273230 9d020c85a4ecae916dc62a2ebd10524659fb7483
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws, Gijs
bugs1134507
milestone40.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1134507 - Implement infopanel to promote Reader View when first available. r=jaws/Gijs 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
@@ -1895,16 +1895,17 @@ 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);
 
 // Enable Service workers for desktop on non-release builds
 #ifdef NIGHTLY_BUILD
 pref("dom.serviceWorkers.enabled", true);
 #endif
 
--- 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
@@ -1463,16 +1463,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
@@ -17,16 +17,17 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 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:AddToPocket",
     "Reader:ArticleGet",
     "Reader:FaviconRequest",
     "Reader:ListStatusRequest",
     "Reader:PocketEnabledGet",
@@ -182,16 +183,30 @@ let ReaderParent = {
       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);
       command.setAttribute("accesskey", gStringBundle.GetStringFromName("readerView.enter.accesskey"));
     }
+
+    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;
+    }
   },
 
   forceShowReaderIcon: function(browser) {
     browser.isArticle = true;
     this.updateReaderButton(browser);
   },
 
   buttonClick(event) {
@@ -223,20 +238,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
@@ -89,16 +89,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
@@ -141,16 +141,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
@@ -118,16 +118,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
--- a/testing/profiles/prefs_general.js
+++ b/testing/profiles/prefs_general.js
@@ -304,18 +304,19 @@ 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);
 user_pref("browser.tabs.remote.autostart.2", 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);
 
 // Don't let PAC generator to set PAC, as mochitest framework has its own PAC
 // rules during testing.
 user_pref("network.proxy.pac_generator", false);
 
 // Make tests run consistently on DevEdition (which has a lightweight theme
 // selected by default).
 user_pref("lightweightThemes.selectedThemeID", "");