diff --git a/mozilla/browser/base/content/browser-sets.inc b/mozilla/browser/base/content/browser-sets.inc
index 4ac3715de41..ec55c4da81b 100644
--- a/mozilla/browser/base/content/browser-sets.inc
+++ b/mozilla/browser/base/content/browser-sets.inc
@@ -148,6 +148,7 @@
#ifdef MOZ_PLACES
+
#else
diff --git a/mozilla/browser/base/content/browser.js b/mozilla/browser/base/content/browser.js
index 25bab03bac5..a06288136e2 100644
--- a/mozilla/browser/base/content/browser.js
+++ b/mozilla/browser/base/content/browser.js
@@ -6294,12 +6294,44 @@ function BookmarkAllTabsCommand() {
}
BookmarkAllTabsCommand.prototype = {
get enabled() {
- //LOG("BookmarkAllTabs.enabled: " + getBrowser().tabContainer.childNodes.length > 1);
return getBrowser().tabContainer.childNodes.length > 1;
},
-
+
execute: function BATC_execute() {
- LOG("BookmarkAllTabs.execute: IMPLEMENT ME");
+ var tabURIs = this._getUniqueTabInfo(getBrowser());
+ PlacesController.showAddMultiBookmarkUI(tabURIs);
+ },
+
+ /**
+ * This function returns a list of nsIURI objects characterizing the
+ * tabs currently open in the given browser. The URIs will appear in the
+ * list in the order in which their corresponding tabs appeared. However,
+ * only the first instance of each URI will be returned.
+ *
+ * @param aTabBrowser the tabBrowser to get the contents of
+ *
+ * @returns a list of nsIURI objects representing unique locations open
+ */
+ _getUniqueTabInfo: function BATC__getUniqueTabInfo(aTabBrowser) {
+ var tabList = [];
+ var seenURIs = [];
+
+ const activeBrowser = aTabBrowser.selectedBrowser;
+ const browsers = aTabBrowser.browsers;
+ for (var i = 0; i < browsers.length; ++i) {
+ var webNav = browsers[i].webNavigation;
+ var uri = webNav.currentURI;
+
+ // skip redundant entries
+ if (uri.spec in seenURIs)
+ continue;
+
+ // add to the set of seen URIs
+ seenURIs[uri.spec] = true;
+
+ tabList.push(uri);
+ }
+ return tabList;
}
};
BookmarkAllTabsCommand.NAME = "Browser:BookmarkAllTabs";
diff --git a/mozilla/browser/components/places/content/bookmarkProperties.js b/mozilla/browser/components/places/content/bookmarkProperties.js
index 47d9b1188f8..c1efa65e705 100755
--- a/mozilla/browser/components/places/content/bookmarkProperties.js
+++ b/mozilla/browser/components/places/content/bookmarkProperties.js
@@ -100,6 +100,7 @@ var BookmarkPropertiesPanel = {
ADD_BOOKMARK_VARIANT: 1,
EDIT_HISTORY_VARIANT: 2,
EDIT_FOLDER_VARIANT: 3,
+ ADD_MULTIPLE_BOOKMARKS_VARIANT: 4,
/**
* The variant identifier for the current instance of the dialog.
@@ -118,8 +119,25 @@ var BookmarkPropertiesPanel = {
_identifierIsURI: function BPP__identifierIsURI() {
switch(this._variant) {
- case this.EDIT_FOLDER_VARIANT: return false;
- default: return true;
+ case this.EDIT_FOLDER_VARIANT:
+ case this.ADD_MULTIPLE_BOOKMARKS_VARIANT:
+ return false;
+ default:
+ return true;
+ }
+ },
+
+ /**
+ * Returns true if this variant of the dialog uses a folder ID as a primary
+ * identifier for the item being edited.
+ */
+
+ _identifierIsFolderID: function BPP__identifierIsFolderID() {
+ switch(this._variant) {
+ case this.EDIT_FOLDER_VARIANT:
+ return true;
+ default:
+ return false;
}
},
@@ -128,8 +146,10 @@ var BookmarkPropertiesPanel = {
*/
_isTitleEditable: function BPP__isTitleEditable() {
switch(this._variant) {
- case this.EDIT_HISTORY_VARIANT: return false;
- default: return true;
+ case this.EDIT_HISTORY_VARIANT:
+ return false;
+ default:
+ return true;
}
},
@@ -138,9 +158,12 @@ var BookmarkPropertiesPanel = {
*/
_isURIEditable: function BPP__isURIEditable() {
switch(this._variant) {
- case this.EDIT_HISTORY_VARIANT: return false;
- case this.EDIT_FOLDER_VARIANT: return false;
- default: return true;
+ case this.EDIT_HISTORY_VARIANT:
+ case this.EDIT_FOLDER_VARIANT:
+ case this.ADD_MULTIPLE_BOOKMARKS_VARIANT:
+ return false;
+ default:
+ return true;
}
},
@@ -149,8 +172,11 @@ var BookmarkPropertiesPanel = {
*/
_isURIVisible: function BPP__isURIVisible() {
switch(this._variant) {
- case this.EDIT_FOLDER_VARIANT: return false;
- default: return true;
+ case this.EDIT_FOLDER_VARIANT:
+ case this.ADD_MULTIPLE_BOOKMARKS_VARIANT:
+ return false;
+ default:
+ return true;
}
},
@@ -160,9 +186,12 @@ var BookmarkPropertiesPanel = {
*/
_isShortcutVisible: function BPP__isShortcutVisible() {
switch(this._variant) {
- case this.EDIT_HISTORY_VARIANT: return false;
- case this.EDIT_FOLDER_VARIANT: return false;
- default: return true;
+ case this.EDIT_HISTORY_VARIANT:
+ case this.EDIT_FOLDER_VARIANT:
+ case this.ADD_MULTIPLE_BOOKMARKS_VARIANT:
+ return false;
+ default:
+ return true;
}
},
@@ -172,10 +201,13 @@ var BookmarkPropertiesPanel = {
*/
_isDeletePossible: function BPP__isDeletePossible() {
switch(this._variant) {
- case this.EDIT_HISTORY_VARIANT: return false;
- case this.ADD_BOOKMARK_VARIANT: return false;
- case this.EDIT_FOLDER_VARIANT: return false;
- default: return true;
+ case this.EDIT_HISTORY_VARIANT:
+ case this.ADD_BOOKMARK_VARIANT:
+ case this.ADD_MULTIPLE_BOOKMARKS_VARIANT:
+ case this.EDIT_FOLDER_VARIANT:
+ return false;
+ default:
+ return true;
}
},
@@ -183,10 +215,13 @@ var BookmarkPropertiesPanel = {
* Returns true if the URI's folder is editable in this variant
* of the dialog.
*/
- _isFolderEditable: function BPP__isFolderVisible() {
+ _isFolderEditable: function BPP__isFolderEditable() {
switch(this._variant) {
- case this.ADD_BOOKMARK_VARIANT: return true;
- default: return false;
+ case this.ADD_BOOKMARK_VARIANT:
+ case this.ADD_MULTIPLE_BOOKMARKS_VARIANT:
+ return true;
+ default:
+ return false;
}
},
@@ -198,7 +233,10 @@ var BookmarkPropertiesPanel = {
switch(this._variant) {
case this.ADD_BOOKMARK_VARIANT:
return this._strings.getString("dialogAcceptLabelAdd");
- default: return this._strings.getString("dialogAcceptLabelEdit");
+ case this.ADD_MULTIPLE_BOOKMARKS_VARIANT:
+ return this._strings.getString("dialogAcceptLabelAddMulti");
+ default:
+ return this._strings.getString("dialogAcceptLabelEdit");
}
},
@@ -214,11 +252,31 @@ var BookmarkPropertiesPanel = {
return this._strings.getString("dialogTitleHistoryEdit");
case this.EDIT_FOLDER_VARIANT:
return this._strings.getString("dialogTitleFolderEdit");
+ case this.ADD_MULTIPLE_BOOKMARKS_VARIANT:
+ return this._strings.getString("dialogTitleAddMulti");
default:
return this._strings.getString("dialogTitleBookmarkEdit");
}
},
+ /**
+ * Returns a string representing the folder tree selection type for
+ * the given dialog variant. This is either "single" when you can only
+ * select one folder (usually because we're dealing with the location
+ * of a child folder, which can only have one parent), or "multiple"
+ * when you can select multiple folders (bookmarks can be in multiple
+ * folders).
+ */
+ _getFolderSelectionType: function BPP__getFolderSelectionType() {
+ switch(this._variant) {
+ case this.ADD_MULTIPLE_BOOKMARKS_VARIANT:
+ case this.EDIT_FOLDER_VARIANT:
+ return "single";
+ default:
+ return "multiple";
+ }
+ },
+
/**
* This method can be run on a URI parameter to ensure that it didn't
* receive a string instead of an nsIURI object.
@@ -239,7 +297,8 @@ var BookmarkPropertiesPanel = {
* @param identifier the URI or folder ID to display the properties for
* @param action -- "add" if this is being triggered from an "add bookmark"
* UI action; or "edit" if this is being triggered from
- * a "properties" UI action
+ * a "properties" UI action; or "addmulti" if we're
+ * trying to create multiple bookmarks
*
* @returns one of the *_VARIANT constants
*/
@@ -253,6 +312,9 @@ var BookmarkPropertiesPanel = {
return this.ADD_BOOKMARK_VARIANT;
}
}
+ else if (action == "addmulti") {
+ return this.ADD_MULTIPLE_BOOKMARKS_VARIANT;
+ }
else { /* Assume "edit" */
if (typeof(identifier) == "number")
return this.EDIT_FOLDER_VARIANT;
@@ -266,6 +328,33 @@ var BookmarkPropertiesPanel = {
}
},
+ /**
+ * This method returns the title string corresponding to a given URI.
+ * If none is available from the bookmark service (probably because
+ * the given URI doesn't appear in bookmarks or history), we synthesize
+ * a title from the first 100 characters of the URI.
+ *
+ * @param uri a nsIURI object for which we want the title
+ *
+ * @returns a title string
+ */
+
+ _getURITitle: function BPP__getURITitle(uri) {
+ this._assertURINotString(uri);
+
+ var title = this._bms.getItemTitle(uri);
+
+ /* If we can't get a title for a new bookmark, let's set it to
+ be the first 100 characters of the URI. */
+ if (title == null) {
+ title = uri.spec;
+ if (title.length > 100) {
+ title = title.substr(0, 100);
+ }
+ }
+ return title;
+ },
+
/**
* This method should be called by the onload of the Bookmark Properties
* dialog to initialize the state of the panel.
@@ -284,9 +373,12 @@ var BookmarkPropertiesPanel = {
this._assertURINotString(identifier);
this._bookmarkURI = identifier;
}
- else {
+ else if (this._identifierIsFolderID()){
this._folderId = identifier;
}
+ else if (this._isVariant(this.ADD_MULTIPLE_BOOKMARKS_VARIANT)) {
+ this._URIList = identifier;
+ }
this._dialogWindow = dialogWindow;
this._controller = controller;
@@ -307,6 +399,7 @@ var BookmarkPropertiesPanel = {
this._folderTree.peerDropTypes = [];
this._folderTree.childDropTypes = [];
this._folderTree.excludeItems = true;
+ this._folderTree.setAttribute("seltype", this._getFolderSelectionType());
var query = this._hist.getNewQuery();
query.setFolders([this._bms.placesRoot], 1);
@@ -324,18 +417,9 @@ var BookmarkPropertiesPanel = {
var document = this._dialogWindow.document;
if (this._identifierIsURI()) {
- this._bookmarkTitle = this._bms.getItemTitle(this._bookmarkURI);
-
- /* If we can't get a title for a new bookmark, let's set it to
- be the first 100 characters of the URI. */
- if (this._isVariant(this.ADD_BOOKMARK_VARIANT) && !this._bookmarkTitle) {
- this._bookmarkTitle = this._bookmarkURI.spec;
- if (this._bookmarkTitle.length > 100) {
- this._bookmarkTitle = this._bookmarkTitle.substr(0, 100);
- }
- }
+ this._bookmarkTitle = this._getURITitle(this._bookmarkURI);
}
- else {
+ else if (this._identifierIsFolderID()){
this._bookmarkTitle = this._bms.getFolderTitle(this._folderId);
}
@@ -458,6 +542,7 @@ var BookmarkPropertiesPanel = {
_saveChanges: function PBD_saveChanges() {
var transactions = [];
var urlbox = this._dialogWindow.document.getElementById("editURLBar");
+ var titlebox = this._dialogWindow.document.getElementById("editTitleBox");
var newURI = this._bookmarkURI;
if (this._identifierIsURI() && this._isURIEditable())
newURI = this._uri(urlbox.value);
@@ -465,24 +550,45 @@ var BookmarkPropertiesPanel = {
if (this._isFolderEditable()) {
var selected = this._folderTree.getSelectionNodes();
- for (var i = 0; i < selected.length; i++) {
- var node = selected[i];
- if (node.type == node.RESULT_TYPE_FOLDER) {
- var folder = node.QueryInterface(Ci.nsINavHistoryFolderResultNode);
- if (!folder.childrenReadOnly) {
- transactions.push(
- new PlacesCreateItemTransaction(newURI, folder.folderId, -1));
+ if (this._identifierIsURI()) {
+ for (var i = 0; i < selected.length; i++) {
+ var node = selected[i];
+ if (node.type == node.RESULT_TYPE_FOLDER) {
+ var folder = node.QueryInterface(Ci.nsINavHistoryFolderResultNode);
+ if (!folder.childrenReadOnly) {
+ transactions.push(
+ new PlacesCreateItemTransaction(newURI, folder.folderId, -1));
+ }
}
}
}
+ else if (this._isVariant(this.ADD_MULTIPLE_BOOKMARKS_VARIANT)) {
+ var node = selected[0];
+ var folder = node.QueryInterface(Ci.nsINavHistoryFolderResultNode);
+
+ var newFolderTrans = new PlacesCreateFolderTransaction(
+ titlebox.value, folder.folderId, -1);
+
+ var childTransactions = [];
+ for (var i = 0; i < this._URIList.length; ++i) {
+ var uri = this._URIList[i];
+ childTransactions.push(
+ new PlacesCreateItemTransaction(uri, -1, -1));
+ childTransactions.push(
+ new PlacesEditItemTitleTransaction(uri,
+ this._getURITitle(uri)));
+ }
+ newFolderTrans.childTransactions = childTransactions;
+
+ transactions.push(newFolderTrans);
+ }
}
- var titlebox = this._dialogWindow.document.getElementById("editTitleBox");
if (this._identifierIsURI())
transactions.push(
new PlacesEditItemTitleTransaction(newURI, titlebox.value));
- else
+ else if (this._identifierIsFolderID())
transactions.push(
new PlacesEditFolderTitleTransaction(this._folderId, titlebox.value));
diff --git a/mozilla/browser/components/places/content/controller.js b/mozilla/browser/components/places/content/controller.js
index dc0b71f819b..18ad72dbfef 100755
--- a/mozilla/browser/components/places/content/controller.js
+++ b/mozilla/browser/components/places/content/controller.js
@@ -1205,6 +1205,19 @@ var PlacesController = {
this._showBookmarkDialog(uri, "add");
},
+ /**
+ * Show an "Add Bookmarks" dialog to allow the adding of a folder full
+ * of bookmarks corresponding to the objects in the uriList. This will
+ * be called most often as the result of a "Bookmark All Tabs..." command.
+ *
+ * @param uriList List of nsIURI objects representing the locations
+ * to be bookmarked.
+ */
+ showAddMultiBookmarkUI: function PC_showAddMultiBookmarkUI(uriList) {
+ NS_ASSERT(uriList.length, "showAddMultiBookmarkUI expects a list of nsIURI objects");
+ this._showBookmarkDialog(uriList, "addmulti");
+ },
+
/**
* Opens the bookmark properties panel for a given URI.
*
@@ -1231,17 +1244,12 @@ var PlacesController = {
* This is an implementation function, and shouldn't be called directly;
* rather, use the specific variant above that corresponds to your situation.
*
- * @param identifier the URI or folder ID to show the dialog for
+ * @param identifier the URI or folder ID or URI list to show
+ * properties for
* @param action "add" or "edit", see _determineVariant in
* bookmarkProperties.js
*/
_showBookmarkDialog: function PC__showBookmarkDialog(identifier, action) {
- // The identifier parameter can be either an integer (for folders) or
- // a nsIURI object (for bookmarks/history items); if it isn't a number
- // here, we're going to make sure it's a URI object rather than a string.
- if (typeof(identifier) != "number")
- this._assertURINotString(identifier);
-
window.openDialog("chrome://browser/content/places/bookmarkProperties.xul",
"", "width=600,height=400,chrome,dependent,modal,resizable",
identifier, this, action);
@@ -2218,7 +2226,7 @@ PlacesAggregateTransaction.prototype = {
undoTransaction: function() {
this.LOG("== UN" + this._name + " (UNAggregate) ============");
this.bookmarks.beginUpdateBatch();
- for (var i = this._transactions.length; i >= 0; --i) {
+ for (var i = this._transactions.length - 1; i >= 0; --i) {
var txn = this._transactions[i];
if (this.container > -1)
txn.container = this.container;
diff --git a/mozilla/browser/locales/en-US/chrome/browser/places/bookmarkProperties.dtd b/mozilla/browser/locales/en-US/chrome/browser/places/bookmarkProperties.dtd
index d167626b930..4d73893222b 100644
--- a/mozilla/browser/locales/en-US/chrome/browser/places/bookmarkProperties.dtd
+++ b/mozilla/browser/locales/en-US/chrome/browser/places/bookmarkProperties.dtd
@@ -19,3 +19,4 @@
+
diff --git a/mozilla/browser/locales/en-US/chrome/browser/places/bookmarkProperties.properties b/mozilla/browser/locales/en-US/chrome/browser/places/bookmarkProperties.properties
index 4e0ffd4af27..6b93d2b9a4e 100644
--- a/mozilla/browser/locales/en-US/chrome/browser/places/bookmarkProperties.properties
+++ b/mozilla/browser/locales/en-US/chrome/browser/places/bookmarkProperties.properties
@@ -1,6 +1,8 @@
dialogAcceptLabelAdd=Add Bookmark
+dialogAcceptLabelAddMulti=Add Bookmarks
dialogAcceptLabelEdit=Save Changes
dialogTitleAdd=Add Bookmark
+dialogTitleAddMulti=Bookmark All Tabs
dialogTitleBookmarkEdit=Bookmark Properties
dialogTitleHistoryEdit=Viewed Page Properties
dialogTitleFolderEdit=Edit Folder Properties