Bug 1124400 - [ReadingList] Add section to bookmarks popup for reading list items and actions, r=Unfocussed.
authorFlorian Quèze <florian@queze.net>
Mon, 23 Feb 2015 13:58:36 +0100
changeset 259125 46aebcd9481e071cf5c280865d85e99313757fd4
parent 259124 f4d73ea8f2264f8ffd03415960603313352ac384
child 259126 0340ca4dd110bb3b3258f267b94cf15cc16c6d0e
child 259141 9aa1baf04e8076a6c08f12601d53fc63e75bc167
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersUnfocussed
bugs1124400
milestone38.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 1124400 - [ReadingList] Add section to bookmarks popup for reading list items and actions, r=Unfocussed.
browser/base/content/browser-menubar.inc
browser/base/content/browser-readinglist.js
browser/base/content/browser.js
browser/base/content/browser.xul
browser/components/customizableui/content/panelUI.inc.xul
browser/locales/en-US/chrome/browser/browser.dtd
browser/themes/linux/browser.css
browser/themes/linux/jar.mn
browser/themes/osx/browser.css
browser/themes/osx/jar.mn
browser/themes/shared/readinglist/readinglist-icon.svg
browser/themes/windows/browser.css
browser/themes/windows/jar.mn
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -439,16 +439,38 @@
         <menupopup id="bookmarksToolbarFolderPopup"
 #ifndef XP_MACOSX
                    placespopup="true"
 #endif
                    context="placesContext"
                    onpopupshowing="if (!this.parentNode._placesView)
                                      new PlacesMenu(event, 'place:folder=TOOLBAR');"/>
       </menu>
+#ifndef XP_MACOSX
+# Disabled on Mac because we can't fill native menupopups asynchronously
+      <menuseparator/>
+      <menu id="menu_readingList"
+            class="menu-iconic bookmark-item"
+            label="&readingList.label;"
+            container="true">
+        <observes element="readingListSidebar" attribute="hidden"/>
+        <menupopup id="readingListPopup"
+#ifndef XP_MACOSX
+                   placespopup="true"
+#endif
+                   onpopupshowing="ReadingListUI.onReadingListPopupShowing(this);">
+          <menuseparator id="viewReadingListSidebarSeparator"/>
+          <menuitem id="viewReadingListSidebar" class="subviewbutton"
+                    oncommand="SidebarUI.toggle('readingListSidebar');"
+                    label="&readingList.showSidebar.label;">
+            <observes element="readingListSidebar" attribute="checked"/>
+          </menuitem>
+        </menupopup>
+      </menu>
+#endif
       <menuseparator id="bookmarksMenuItemsSeparator"/>
       <!-- Bookmarks menu items -->
       <menuseparator builder="end"
                      class="hide-if-empty-places-result"/>
       <menuitem id="menu_unsortedBookmarks"
                 label="&unsortedBookmarksCmd.label;"
                 oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks');"/>
     </menupopup>
--- a/browser/base/content/browser-readinglist.js
+++ b/browser/base/content/browser-readinglist.js
@@ -1,14 +1,17 @@
 /*
 # 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/.
 */
 
+XPCOMUtils.defineLazyModuleGetter(this, "ReadingList",
+  "resource:///modules/readinglist/ReadingList.jsm");
+
 let ReadingListUI = {
   /**
    * Initialize the ReadingList UI.
    */
   init() {
     Preferences.observe("browser.readinglist.enabled", this.updateUI, this);
     this.updateUI();
   },
@@ -60,9 +63,75 @@ let ReadingListUI = {
   /**
    * Hide the ReadingList sidebar, if it is currently shown.
    */
   hideSidebar() {
     if (this.isSidebarOpen) {
       SidebarUI.hide();
     }
   },
+
+  onReadingListPopupShowing(target) {
+    if (target.id == "BMB_readingListPopup") {
+      // Setting this class in the .xul file messes with the way
+      // browser-places.js inserts bookmarks in the menu.
+      document.getElementById("BMB_viewReadingListSidebar")
+              .classList.add("panel-subview-footer");
+    }
+
+    while (!target.firstChild.id)
+      target.firstChild.remove();
+
+    let classList = "menuitem-iconic bookmark-item menuitem-with-favicon";
+    let insertPoint = target.firstChild;
+    if (insertPoint.classList.contains("subviewbutton"))
+      classList += " subviewbutton";
+
+    ReadingList.getItems().then(items => {
+      for (let item of items) {
+        let menuitem = document.createElement("menuitem");
+        menuitem.setAttribute("label", item.title || item.url.spec);
+        menuitem.setAttribute("class", classList);
+
+        let node = menuitem._placesNode = {
+          // Passing the PlacesUtils.nodeIsURI check is required for the
+          // onCommand handler to load our URI.
+          type: Ci.nsINavHistoryResultNode.RESULT_TYPE_URI,
+
+          // makes PlacesUIUtils.canUserRemove return false.
+          // The context menu is broken without this.
+          parent: {type: Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER},
+
+          // A -1 id makes this item a non-bookmark, which avoids calling
+          // PlacesUtils.annotations.itemHasAnnotation to check if the
+          // bookmark should be opened in the sidebar (this call fails for
+          // readinglist item, and breaks loading our URI).
+          itemId: -1,
+
+          // Used by the tooltip and onCommand handlers.
+          uri: item.url.spec,
+
+          // Used by the tooltip.
+          title: item.title
+        };
+
+        Favicons.getFaviconURLForPage(item.url, uri => {
+          if (uri) {
+            menuitem.setAttribute("image",
+                                  Favicons.getFaviconLinkForIcon(uri).spec);
+          }
+        });
+
+        target.insertBefore(menuitem, insertPoint);
+      }
+
+      if (!items.length) {
+        let menuitem = document.createElement("menuitem");
+        let bundle =
+          Services.strings.createBundle("chrome://browser/locale/places/places.properties");
+        menuitem.setAttribute("label", bundle.GetStringFromName("bookmarksMenuEmptyFolder"));
+        menuitem.setAttribute("class", "bookmark-item");
+        menuitem.setAttribute("disabled", true);
+        target.insertBefore(menuitem, insertPoint);
+      }
+    });
+  }
 };
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -32,16 +32,19 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "GMPInstallManager",
                                   "resource://gre/modules/GMPInstallManager.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
                                   "resource://gre/modules/NewTabUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch",
                                   "resource:///modules/ContentSearch.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AboutHome",
                                   "resource:///modules/AboutHome.jsm");
+XPCOMUtils.defineLazyServiceGetter(this, "Favicons",
+                                   "@mozilla.org/browser/favicon-service;1",
+                                   "mozIAsyncFavicons");
 XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
                                    "@mozilla.org/network/dns-service;1",
                                    "nsIDNSService");
 
 const nsIWebNavigation = Ci.nsIWebNavigation;
 
 var gLastBrowserCharset = null;
 var gProxyFavIcon = null;
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -945,16 +945,32 @@
                   container="true">
               <menupopup id="BMB_unsortedBookmarksPopup"
                          placespopup="true"
                          context="placesContext"
                          onpopupshowing="if (!this.parentNode._placesView)
                                            new PlacesMenu(event, 'place:folder=UNFILED_BOOKMARKS',
                                                           PlacesUIUtils.getViewForNode(this.parentNode.parentNode).options);"/>
             </menu>
+            <menuseparator>
+              <observes element="readingListSidebar" attribute="hidden"/>
+            </menuseparator>
+            <menu id="BMB_readingList"
+                  class="menu-iconic bookmark-item subviewbutton"
+                  label="&readingList.label;"
+                  container="true">
+              <observes element="readingListSidebar" attribute="hidden"/>
+              <menupopup id="BMB_readingListPopup"
+                         placespopup="true"
+                         onpopupshowing="ReadingListUI.onReadingListPopupShowing(this);">
+                <menuitem id="BMB_viewReadingListSidebar" class="subviewbutton"
+                          oncommand="SidebarUI.show('readingListSidebar');"
+                          label="&readingList.showSidebar.label;"/>
+              </menupopup>
+            </menu>
             <menuseparator/>
             <!-- Bookmarks menu items will go here -->
             <menuitem id="BMB_bookmarksShowAll"
                       class="subviewbutton panel-subview-footer"
                       label="&showAllBookmarks2.label;"
                       command="Browser:ShowAllBookmarks"
                       key="manBookmarkKb"/>
           </menupopup>
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -121,16 +121,27 @@
         <toolbarbutton id="panelMenu_bookmarksToolbar"
                        label="&personalbarCmd.label;"
                        class="subviewbutton cui-withicon"
                        oncommand="PlacesCommandHook.showPlacesOrganizer('BookmarksToolbar'); PanelUI.hide();"/>
         <toolbarbutton id="panelMenu_unsortedBookmarks"
                        label="&unsortedBookmarksCmd.label;"
                        class="subviewbutton cui-withicon"
                        oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks'); PanelUI.hide();"/>
+        <toolbarseparator>
+          <observes element="readingListSidebar" attribute="hidden"/>
+        </toolbarseparator>
+        <toolbarbutton id="panelMenu_viewReadingListSidebar"
+                       label="&readingList.showSidebar.label;"
+                       class="subviewbutton"
+                       key="key_readingListSidebar"
+                       oncommand="SidebarUI.toggle('readingListSidebar'); PanelUI.hide();">
+          <observes element="readingListSidebar" attribute="checked"/>
+          <observes element="readingListSidebar" attribute="hidden"/>
+        </toolbarbutton>
         <toolbarseparator class="small-separator"/>
         <toolbaritem id="panelMenu_bookmarksMenu"
                      orient="vertical"
                      smoothscroll="false"
                      onclick="if (event.button == 1) BookmarkingUI.onPanelMenuViewCommand(event, this._placesView);"
                      oncommand="BookmarkingUI.onPanelMenuViewCommand(event, this._placesView);"
                      flatList="true"
                      tooltip="bhTooltip">
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -842,17 +842,16 @@ just addresses the organization to follo
 <!ENTITY emeLearnMoreContextMenu.accesskey        "D">
 <!ENTITY emeNotificationsNotNow.label             "Not now">
 <!ENTITY emeNotificationsNotNow.accesskey         "N">
 <!ENTITY emeNotificationsDontAskAgain.label       "Don't ask me again">
 <!ENTITY emeNotificationsDontAskAgain.accesskey   "D">
 
 <!ENTITY readingList.label                        "Reading List">
 <!ENTITY readingList.sidebar.commandKey           "R">
-<!-- Pre-landed string for bug 1124400 -->
 <!ENTITY readingList.showSidebar.label            "Show Reading List Sidebar">
 <!-- Pre-landed string for bug 1124153 -->
 <!ENTITY readingList.sidebar.showMore.label       "Show moreā€¦">
 <!-- Pre-landed string for bug 1133662 -->
 <!ENTITY readingList.sidebar.emptyText            "Add articles to your Reading List to save them for later and find them easily when you need them.">
 <!-- Pre-landed string for bug 1123525 -->
 <!ENTITY readingList.sidebar.delete.tooltip       "Remove this from your Reading List">
 <!-- Pre-landed strings for bug 1123519 -->
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -513,16 +513,21 @@ menuitem:not([type]):not(.menuitem-toolt
   list-style-image: url("chrome://browser/skin/places/bookmarksToolbar.png");
 }
 
 #BMB_unsortedBookmarks,
 #panelMenu_unsortedBookmarks {
   list-style-image: url("chrome://browser/skin/places/unsortedBookmarks.png");
 }
 
+#menu_readingList,
+#BMB_readingList {
+  list-style-image: url("chrome://browser/skin/readinglist/readinglist-icon.svg");
+}
+
 #menu_openDownloads {
   list-style-image: url("chrome://browser/skin/Toolbar-small.png");
   -moz-image-region: rect(0px 16px 16px 0px);
 }
 
 #menu_openAddons {
   list-style-image: url("chrome://mozapps/skin/extensions/extensionGeneric-16.png");
 }
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -86,16 +86,17 @@ browser.jar:
   skin/classic/browser/Toolbar-inverted.png
   skin/classic/browser/Toolbar-small.png
   skin/classic/browser/undoCloseTab.png                        (../shared/undoCloseTab.png)
   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-mode-16.png             (../shared/reader/reader-mode-16.png)
+  skin/classic/browser/readinglist/readinglist-icon.svg (../shared/readinglist/readinglist-icon.svg)
   skin/classic/browser/readinglist/sidebar.css        (../shared/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
   skin/classic/browser/webRTC-shareMicrophone-64.png
   skin/classic/browser/webRTC-sharingMicrophone-16.png (../shared/webrtc/webRTC-sharingMicrophone-16.png)
   skin/classic/browser/webRTC-shareScreen-16.png      (../shared/webrtc/webRTC-shareScreen-16.png)
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -558,16 +558,21 @@ toolbarpaletteitem[place="palette"] > #p
     list-style-image: url("chrome://browser/skin/places/bookmarksToolbar@2x.png");
   }
 
   #BMB_unsortedBookmarks {
     list-style-image: url("chrome://browser/skin/places/unfiledBookmarks@2x.png");
   }
 }
 
+/* #menu_readingList, svg icons don't work in the mac native menubar */
+#BMB_readingList {
+  list-style-image: url("chrome://browser/skin/readinglist/readinglist-icon.svg");
+}
+
 /* ----- PRIMARY TOOLBAR BUTTONS ----- */
 
 toolbar .toolbarbutton-1:not([type="menu-button"]),
 .toolbarbutton-1 > .toolbarbutton-menubutton-button,
 .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
   -moz-box-orient: vertical;
   height: 24px;
   padding: 0;
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -137,16 +137,17 @@ browser.jar:
   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-mode-16.png             (../shared/reader/reader-mode-16.png)
   skin/classic/browser/reader-mode-16@2x.png          (../shared/reader/reader-mode-16@2x.png)
+  skin/classic/browser/readinglist/readinglist-icon.svg (../shared/readinglist/readinglist-icon.svg)
   skin/classic/browser/readinglist/sidebar.css        (../shared/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
   skin/classic/browser/webRTC-sharingDevice-16.png    (../shared/webrtc/webRTC-sharingDevice-16.png)
   skin/classic/browser/webRTC-sharingDevice-16@2x.png (../shared/webrtc/webRTC-sharingDevice-16@2x.png)
   skin/classic/browser/webRTC-shareMicrophone-16.png
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/readinglist/readinglist-icon.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16">
+  <rect x="4.8" y="6.4" fill="#808080" width="11.2" height="3.2"/>
+  <rect x="4.8" y="11.2" fill="#808080" width="11.2" height="3.2"/>
+  <rect x="4.8" y="1.6" fill="#808080" width="11.2" height="3.2"/>
+  <circle fill="#808080" cx="1.6" cy="3.2" r="1.6"/>
+  <circle fill="#808080" cx="1.6" cy="8" r="1.6"/>
+  <circle fill="#808080" cx="1.6" cy="12.8" r="1.6"/>
+</svg>
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -2521,16 +2521,22 @@ notification[value="translation"] {
 }
 
 #BMB_unsortedBookmarks,
 #panelMenu_unsortedBookmarks {
   list-style-image: url("chrome://browser/skin/places/unsortedBookmarks.png");
   -moz-image-region: auto;
 }
 
+#menu_readingList,
+#BMB_readingList {
+  list-style-image: url("chrome://browser/skin/readinglist/readinglist-icon.svg");
+  -moz-image-region: auto;
+}
+
 /* ::::: Keyboard UI Panel ::::: */
 
 .KUI-panel {
   -moz-appearance: none;
   background: rgba(27%,27%,27%,.9) url(KUI-background.png) repeat-x;
   color: white;
   border-style: none;
   border-radius: 20px;
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -105,16 +105,17 @@ browser.jar:
         skin/classic/browser/undoCloseTab@2x.png                     (../shared/undoCloseTab@2x.png)
         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-mode-16.png                      (../shared/reader/reader-mode-16.png)
+        skin/classic/browser/readinglist/readinglist-icon.svg        (../shared/readinglist/readinglist-icon.svg)
         skin/classic/browser/readinglist/sidebar.css                 (../shared/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
         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
@@ -571,16 +572,17 @@ browser.jar:
         skin/classic/aero/browser/undoCloseTab@2x.png                     (../shared/undoCloseTab@2x.png)
         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-mode-16.png                (../shared/reader/reader-mode-16.png)
+        skin/classic/aero/browser/readinglist/readinglist-icon.svg  (../shared/readinglist/readinglist-icon.svg)
         skin/classic/aero/browser/readinglist/sidebar.css           (../shared/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
         skin/classic/aero/browser/webRTC-shareDevice-64.png
         skin/classic/aero/browser/webRTC-sharingDevice-16.png             (../shared/webrtc/webRTC-sharingDevice-16.png)
         skin/classic/aero/browser/webRTC-shareMicrophone-16.png