diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
index 5091d88192c6..d977a9b1c9c1 100644
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -496,6 +496,8 @@ pref("browser.bookmarks.autoExportHTML", false);
// 0: no backups created (and deletes all existing backups)
pref("browser.bookmarks.max_backups", 15);
+pref("browser.bookmarks.showRecentlyBookmarked", true);
+
// Scripts & Windows prefs
pref("dom.disable_open_during_load", true);
pref("javascript.options.showInConsole", true);
diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js
index d2d7c9b7a514..4a80c56dacc3 100644
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -1326,8 +1326,8 @@ var BookmarkingUI = {
return;
}
- this._updateRecentBookmarks(document.getElementById("BMB_recentBookmarks"),
- "subviewbutton");
+ this._initRecentBookmarks(document.getElementById("BMB_recentBookmarks"),
+ "subviewbutton");
if (!this._popupNeedsUpdate)
return;
@@ -1362,7 +1362,68 @@ var BookmarkingUI = {
});
},
- _updateRecentBookmarks: function(aHeaderItem, extraCSSClass = "") {
+ RECENTLY_BOOKMARKED_PREF: "browser.bookmarks.showRecentlyBookmarked",
+
+ _initRecentBookmarks(aHeaderItem, aExtraCSSClass) {
+ this._populateRecentBookmarks(aHeaderItem, aExtraCSSClass);
+
+ // Add observers and listeners and remove them again when the menupopup closes.
+
+ let bookmarksMenu = aHeaderItem.parentNode;
+ let placesContextMenu = document.getElementById("placesContext");
+
+ let prefObserver = () => {
+ this._populateRecentBookmarks(aHeaderItem, aExtraCSSClass);
+ };
+
+ let updatePlacesContextMenu = (shouldHidePrefUI = false) => {
+ let prefEnabled = !shouldHidePrefUI && Services.prefs.getBoolPref(this.RECENTLY_BOOKMARKED_PREF);
+ document.getElementById("placesContext_showRecentlyBookmarked").hidden = shouldHidePrefUI || prefEnabled;
+ document.getElementById("placesContext_hideRecentlyBookmarked").hidden = shouldHidePrefUI || !prefEnabled;
+ document.getElementById("placesContext_recentlyBookmarkedSeparator").hidden = shouldHidePrefUI;
+ };
+
+ let onPlacesContextMenuShowing = event => {
+ if (event.target == event.currentTarget) {
+ let triggerPopup = event.target.triggerNode;
+ while (triggerPopup && triggerPopup.localName != "menupopup") {
+ triggerPopup = triggerPopup.parentNode;
+ }
+ let shouldHidePrefUI = triggerPopup != bookmarksMenu;
+ updatePlacesContextMenu(shouldHidePrefUI);
+ }
+ };
+
+ let onBookmarksMenuHidden = event => {
+ if (event.target == event.currentTarget) {
+ updatePlacesContextMenu(true);
+
+ Services.prefs.removeObserver(this.RECENTLY_BOOKMARKED_PREF, prefObserver, false);
+ placesContextMenu.removeEventListener("popupshowing", onPlacesContextMenuShowing);
+ bookmarksMenu.removeEventListener("popuphidden", onBookmarksMenuHidden);
+ }
+ };
+
+ Services.prefs.addObserver(this.RECENTLY_BOOKMARKED_PREF, prefObserver, false);
+ placesContextMenu.addEventListener("popupshowing", onPlacesContextMenuShowing);
+ bookmarksMenu.addEventListener("popuphidden", onBookmarksMenuHidden);
+ },
+
+ _populateRecentBookmarks(aHeaderItem, aExtraCSSClass = "") {
+ while (aHeaderItem.nextSibling &&
+ aHeaderItem.nextSibling.localName == "menuitem") {
+ aHeaderItem.nextSibling.remove();
+ }
+
+ let shouldShow = Services.prefs.getBoolPref(this.RECENTLY_BOOKMARKED_PREF);
+ let separator = aHeaderItem.previousSibling;
+ aHeaderItem.hidden = !shouldShow;
+ separator.hidden = !shouldShow;
+
+ if (!shouldShow) {
+ return;
+ }
+
const kMaxResults = 5;
let options = PlacesUtils.history.getNewQueryOptions();
@@ -1372,11 +1433,6 @@ var BookmarkingUI = {
options.maxResults = kMaxResults;
let query = PlacesUtils.history.getNewQuery();
- while (aHeaderItem.nextSibling &&
- aHeaderItem.nextSibling.localName == "menuitem") {
- aHeaderItem.nextSibling.remove();
- }
-
let onItemCommand = function (aEvent) {
let item = aEvent.target;
openUILink(item.getAttribute("targetURI"), aEvent);
@@ -1397,8 +1453,9 @@ var BookmarkingUI = {
"menuitem");
item.setAttribute("label", title || uri);
item.setAttribute("targetURI", uri);
+ item.setAttribute("context", "hideRecentlyBookmarked");
item.setAttribute("class", "menuitem-iconic menuitem-with-favicon bookmark-item " +
- extraCSSClass);
+ aExtraCSSClass);
item.addEventListener("command", onItemCommand);
if (icon) {
item.setAttribute("image", icon);
@@ -1407,6 +1464,15 @@ var BookmarkingUI = {
}
root.containerOpen = false;
aHeaderItem.parentNode.insertBefore(fragment, aHeaderItem.nextSibling);
+ aHeaderItem.setAttribute("context", "hideRecentlyBookmarked");
+ },
+
+ showRecentlyBookmarked() {
+ Services.prefs.setBoolPref(this.RECENTLY_BOOKMARKED_PREF, true);
+ },
+
+ hideRecentlyBookmarked() {
+ Services.prefs.setBoolPref(this.RECENTLY_BOOKMARKED_PREF, false);
},
/**
@@ -1625,7 +1691,7 @@ var BookmarkingUI = {
this._updateBookmarkPageMenuItem();
PlacesCommandHook.updateBookmarkAllTabsCommand();
- this._updateRecentBookmarks(document.getElementById("menu_recentBookmarks"));
+ this._initRecentBookmarks(document.getElementById("menu_recentBookmarks"));
},
_showBookmarkedNotification: function BUI_showBookmarkedNotification() {
diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul
index 87800a90e12c..e57843a3f11e 100644
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -383,7 +383,35 @@
#include browser-context.inc
-
+
+
+
+
+
+
+
+
+
diff --git a/browser/components/places/content/controller.js b/browser/components/places/content/controller.js
index 0f722031f414..b38feecfba37 100644
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -560,6 +560,8 @@ PlacesController.prototype = {
* Detects information (meta-data rules) about the current selection in the
* view (see _buildSelectionMetadata) and sets the visibility state for each
* of the menu-items in the given popup with the following rules applied:
+ * 0) The "ignoreitem" attribute may be set to "true" for this code not to
+ * handle that menuitem.
* 1) The "selectiontype" attribute may be set on a menu-item to "single"
* if the menu-item should be visible only if there is a single node
* selected, or to "multiple" if the menu-item should be visible only if
@@ -601,6 +603,9 @@ PlacesController.prototype = {
var usableItemCount = 0;
for (var i = 0; i < aPopup.childNodes.length; ++i) {
var item = aPopup.childNodes[i];
+ if (item.getAttribute("ignoreitem") == "true") {
+ continue;
+ }
if (item.localName != "menuseparator") {
// We allow pasting into tag containers, so special case that.
var hideIfNoIP = item.getAttribute("hideifnoinsertionpoint") == "true" &&
diff --git a/browser/locales/en-US/chrome/browser/browser.dtd b/browser/locales/en-US/chrome/browser/browser.dtd
index 567a033718c2..315601ca8e1e 100644
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -171,6 +171,10 @@ These should match what Safari and other Apple applications use on OS X Lion. --
+
+
+
+