/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Pierre Chanial . * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ var NC_NS, WEB_NS, RDF_NS, XUL_NS, NC_NS_CMD; // definition of the services frequently used for bookmarks var kRDFContractID; var kRDFSVCIID; var kRDFRSCIID; var kRDFLITIID; var RDF; var kRDFCContractID; var kRDFCIID; var RDFC; var kRDFCUContractID; var kRDFCUIID; var RDFCU; var BMDS; var kBMSVCIID; var BMSVC; var kPREFContractID; var kPREFIID; var PREF; var kSOUNDContractID; var kSOUNDIID; var SOUND; var kWINDOWContractID; var kWINDOWIID; var WINDOWSVC; var kDSContractID; var kDSIID; var DS; var gLoadInBackground = false; // should be moved in a separate file function initServices() { NC_NS = "http://home.netscape.com/NC-rdf#"; WEB_NS = "http://home.netscape.com/WEB-rdf#"; RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; NC_NS_CMD = NC_NS + "command?cmd="; kRDFContractID = "@mozilla.org/rdf/rdf-service;1"; kRDFSVCIID = Components.interfaces.nsIRDFService; kRDFRSCIID = Components.interfaces.nsIRDFResource; kRDFLITIID = Components.interfaces.nsIRDFLiteral; RDF = Components.classes[kRDFContractID].getService(kRDFSVCIID); kRDFCContractID = "@mozilla.org/rdf/container;1"; kRDFCIID = Components.interfaces.nsIRDFContainer; RDFC = Components.classes[kRDFCContractID].createInstance(kRDFCIID); kRDFCUContractID = "@mozilla.org/rdf/container-utils;1"; kRDFCUIID = Components.interfaces.nsIRDFContainerUtils; RDFCU = Components.classes[kRDFCUContractID].getService(kRDFCUIID); kPREFContractID = "@mozilla.org/preferences-service;1"; kPREFIID = Components.interfaces.nsIPrefService; try { PREF = Components.classes[kPREFContractID].getService(kPREFIID) .getBranch(null); } catch (e) {} kSOUNDContractID = "@mozilla.org/sound;1"; kSOUNDIID = Components.interfaces.nsISound; try { SOUND = Components.classes[kSOUNDContractID].createInstance(kSOUNDIID); } catch (e) {} kWINDOWContractID = "@mozilla.org/appshell/window-mediator;1"; kWINDOWIID = Components.interfaces.nsIWindowMediator; try { WINDOWSVC = Components.classes[kWINDOWContractID].getService(kWINDOWIID); } catch (e) {} kDSContractID = "@mozilla.org/widget/dragservice;1"; kDSIID = Components.interfaces.nsIDragService; try { DS = Components.classes[kDSContractID].getService(kDSIID); } catch (e) {} } function initBMService() { kBMSVCIID = Components.interfaces.nsIBookmarksService; BMDS = RDF.GetDataSource("rdf:bookmarks"); BMSVC = BMDS.QueryInterface(kBMSVCIID); BookmarkTransaction.prototype.RDFC = RDFC; BookmarkTransaction.prototype.BMDS = BMDS; } /** * XXX - 04/16/01 * ACK! massive command name collision problems are causing big issues * in getting this stuff to work in the Navigator window. For sanity's * sake, we need to rename all the commands to be of the form cmd_bm_* * otherwise there'll continue to be problems. For now, we're just * renaming those that affect the personal toolbar (edit operations, * which were clashing with the textfield controller) * * There are also several places that need to be updated if you need * to change a command name. * 1) the controller... * - in bookmarksTree.xml if the command is tree-specifc * - in bookmarksMenu.js if the command is DOM-specific * - in bookmarks.js otherwise * 2) the command nodes in the overlay or xul file * 3) the command human-readable name key in bookmarks.properties * 4) the function 'getCommands' in bookmarks.js */ var BookmarksCommand = { ///////////////////////////////////////////////////////////////////////////// // This method constructs a menuitem for a context menu for the given command. // This is implemented by the client so that it can intercept menuitem naming // as appropriate. createMenuItem: function (aDisplayName, aCommandName, aSelection) { var xulElement = document.createElementNS(XUL_NS, "menuitem"); xulElement.setAttribute("cmd", aCommandName); var cmd = "cmd_" + aCommandName.substring(NC_NS_CMD.length); xulElement.setAttribute("command", cmd); switch (aCommandName) { case NC_NS_CMD + "bm_expandfolder": var shouldCollapse = true; for (var i=0; i 0 && common[common.length-1] == aNewArray[i]) continue; if (aNewArray[i] == aOldArray[j]) common.push(aNewArray[i]); } } return common; }, flattenEnumerator: function (aEnumerator) { if ("_index" in aEnumerator) return aEnumerator._inner; var temp = []; while (aEnumerator.hasMoreElements()) temp.push(aEnumerator.getNext()); return temp; }, ///////////////////////////////////////////////////////////////////////////// // For a given URI (a unique identifier of a resource in the graph) return // an enumeration of applicable commands for that URI. getCommands: function (aNodeID) { var type = BookmarksUtils.resolveType(aNodeID); if (!type) return null; var commands = []; // menu order: // // bm_expandfolder // bm_open // bm_openinnewwindow // bm_openinnewtab // --------------------- // bm_newfolder // --------------------- // bm_cut // bm_copy // bm_paste // --------------------- // bm_delete // --------------------- // bm_properties switch (type) { case "BookmarkSeparator": commands = ["bm_newfolder", "bm_separator", "bm_cut", "bm_copy", "bm_paste", "bm_separator", "bm_delete", "bm_separator", "bm_properties"]; break; case "Bookmark": commands = ["bm_open", "bm_openinnewwindow", "bm_openinnewtab", "bm_separator", "bm_newfolder", "bm_sortfolder", "bm_sortfolderbyname", "bm_separator", "bm_cut", "bm_copy", "bm_paste", "bm_movebookmark", "bm_separator", "bm_rename", "bm_delete", "bm_separator", "bm_properties"]; break; case "Folder": commands = ["bm_expandfolder", "bm_managefolder", "bm_separator", "bm_newfolder", "bm_sortfolder", "bm_sortfolderbyname", "bm_separator", "bm_cut", "bm_copy", "bm_paste", "bm_movebookmark", "bm_separator", "bm_rename", "bm_delete", "bm_separator", "bm_properties"]; break; case "FolderGroup": commands = ["bm_open", "bm_openinnewwindow", "bm_expandfolder", "bm_separator", "bm_newfolder", "bm_sortfolder", "bm_sortfolderbyname", "bm_separator", "bm_cut", "bm_copy", "bm_paste", "bm_movebookmark", "bm_separator", "bm_rename", "bm_delete", "bm_separator", "bm_properties"]; break; case "PersonalToolbarFolder": commands = ["bm_newfolder", "bm_sortfolder", "bm_sortfolderbyname", "bm_separator", "bm_cut", "bm_copy", "bm_paste", "bm_movebookmark", "bm_separator", "bm_rename", "bm_delete", "bm_separator", "bm_properties"]; break; case "IEFavoriteFolder": commands = ["bm_expandfolder", "bm_separator", "bm_delete"]; break; case "IEFavorite": commands = ["bm_open", "bm_openinnewwindow", "bm_openinnewtab", "bm_separator", "bm_copy"]; break; case "FileSystemObject": commands = ["bm_open", "bm_openinnewwindow", "bm_openinnewtab", "bm_separator", "bm_copy"]; break; default: commands = []; } return new CommandArrayEnumerator(commands); }, ///////////////////////////////////////////////////////////////////////////// // For a given target ID, return an enumeration that contains the possible // commands. getValidCommands: function (aTargetID) { var valid = ["bm_open", "bm_openinnewwindow", "bm_openinnewtab", "bm_managefolder", "bm_separator", "bm_newfolder", "bm_sortfolder", "bm_sortfolderbyname", "bm_cut", "bm_copy", "bm_paste", "bm_movebookmark", "bm_rename", "bm_delete", "bm_properties"]; if (aTargetID != "bookmarks-context-menu") valid.push("bm_expandfolder"); return new CommandArrayEnumerator(valid); }, ///////////////////////////////////////////////////////////////////////////// // Retrieve the human-readable name for a particular command. Used when // manufacturing a UI to invoke commands. getCommandName: function (aCommand) { var cmdName = aCommand.substring(NC_NS_CMD.length); return BookmarksUtils.getLocaleString ("cmd_" + cmdName); /* try { // Note: this will succeed only if there's a string in the bookmarks // string bundle for this command name. Otherwise, // will throw, we'll catch & stifle the error, and look up the command // name in the datasource. return BookmarksUtils.getLocaleString ("cmd_" + cmdName); } catch (e) { } // XXX - WORK TO DO HERE! (rjc will cry if we don't fix this) // need to ask the ds for the commands for this node, however we don't // have the right params. This is kind of a problem. dump("*** BAD! EVIL! WICKED! NO! ACK! ARGH! ORGH!"+aCommand+"\n"); const rName = RDF.GetResource(NC_NS + "Name"); const rSource = RDF.GetResource(aNodeID); return BMDS.GetTarget(rSource, rName, true).Value; */ }, /////////////////////////////////////////////////////////////////////////// // Execute a command with the given source and arguments doBookmarksCommand: function (aSource, aCommand, aArgumentsArray) { var rCommand = RDF.GetResource(aCommand); var kSuppArrayContractID = "@mozilla.org/supports-array;1"; var kSuppArrayIID = Components.interfaces.nsISupportsArray; var sourcesArray = Components.classes[kSuppArrayContractID].createInstance(kSuppArrayIID); if (aSource) { sourcesArray.AppendElement(aSource); } var argsArray = Components.classes[kSuppArrayContractID].createInstance(kSuppArrayIID); var length = aArgumentsArray?aArgumentsArray.length:0; for (var i = 0; i < length; ++i) { var rArc = RDF.GetResource(aArgumentsArray[i].property); argsArray.AppendElement(rArc); var rValue = null; if ("resource" in aArgumentsArray[i]) { rValue = RDF.GetResource(aArgumentsArray[i].resource); } else rValue = RDF.GetLiteral(aArgumentsArray[i].literal); argsArray.AppendElement(rValue); } // Exec the command in the Bookmarks datasource. BMDS.DoCommand(sourcesArray, rCommand, argsArray); }, undoBookmarkTransaction: function () { BMSVC.transactionManager.undoTransaction(); BookmarksUtils.flushDataSource(); }, redoBookmarkTransaction: function () { BMSVC.transactionManager.redoTransaction(); BookmarksUtils.flushDataSource(); }, manageFolder: function (aSelection) { openDialog("chrome://communicator/content/bookmarks/bookmarksManager.xul", "", "chrome,all,dialog=no", aSelection.item[0].Value); }, cutBookmark: function (aSelection) { this.copyBookmark(aSelection); BookmarksUtils.removeSelection("cut", aSelection); }, copyBookmark: function (aSelection) { const kSuppArrayContractID = "@mozilla.org/supports-array;1"; const kSuppArrayIID = Components.interfaces.nsISupportsArray; var itemArray = Components.classes[kSuppArrayContractID].createInstance(kSuppArrayIID); const kSuppWStringContractID = "@mozilla.org/supports-string;1"; const kSuppWStringIID = Components.interfaces.nsISupportsString; var bmstring = Components.classes[kSuppWStringContractID].createInstance(kSuppWStringIID); var unicodestring = Components.classes[kSuppWStringContractID].createInstance(kSuppWStringIID); var htmlstring = Components.classes[kSuppWStringContractID].createInstance(kSuppWStringIID); var sBookmarkItem = ""; var sTextUnicode = ""; var sTextHTML = ""; for (var i = 0; i < aSelection.length; ++i) { var url = BookmarksUtils.getProperty(aSelection.item[i], NC_NS+"URL" ); var name = BookmarksUtils.getProperty(aSelection.item[i], NC_NS+"Name"); sBookmarkItem += aSelection.item[i].Value + "\n"; sTextUnicode += url + "\n"; sTextHTML += "" + name + ""; } const kXferableContractID = "@mozilla.org/widget/transferable;1"; const kXferableIID = Components.interfaces.nsITransferable; var xferable = Components.classes[kXferableContractID].createInstance(kXferableIID); xferable.addDataFlavor("moz/bookmarkclipboarditem"); bmstring.data = sBookmarkItem; xferable.setTransferData("moz/bookmarkclipboarditem", bmstring, sBookmarkItem.length*2); xferable.addDataFlavor("text/html"); htmlstring.data = sTextHTML; xferable.setTransferData("text/html", htmlstring, sTextHTML.length*2); xferable.addDataFlavor("text/unicode"); unicodestring.data = sTextUnicode; xferable.setTransferData("text/unicode", unicodestring, sTextUnicode.length*2); const kClipboardContractID = "@mozilla.org/widget/clipboard;1"; const kClipboardIID = Components.interfaces.nsIClipboard; var clipboard = Components.classes[kClipboardContractID].getService(kClipboardIID); clipboard.setData(xferable, null, kClipboardIID.kGlobalClipboard); }, pasteBookmark: function (aTarget) { const kXferableContractID = "@mozilla.org/widget/transferable;1"; const kXferableIID = Components.interfaces.nsITransferable; var xferable = Components.classes[kXferableContractID].createInstance(kXferableIID); xferable.addDataFlavor("moz/bookmarkclipboarditem"); xferable.addDataFlavor("text/x-moz-url"); xferable.addDataFlavor("text/unicode"); const kClipboardContractID = "@mozilla.org/widget/clipboard;1"; const kClipboardIID = Components.interfaces.nsIClipboard; var clipboard = Components.classes[kClipboardContractID].getService(kClipboardIID); clipboard.getData(xferable, kClipboardIID.kGlobalClipboard); var flavour = { }; var data = { }; var length = { }; xferable.getAnyTransferData(flavour, data, length); var items, name, url; data = data.value.QueryInterface(Components.interfaces.nsISupportsString).data; switch (flavour.value) { case "moz/bookmarkclipboarditem": items = data.split("\n"); // since data are ended by \n, remove the last empty node items.pop(); for (var i=0; i 0; case "cmd_redo": case "cmd_bm_redo": return BMSVC.transactionManager.numberOfRedoItems > 0; case "cmd_bm_paste": if (!(aTarget && BookmarksUtils.isValidTargetContainer(aTarget.parent))) return false; const kClipboardContractID = "@mozilla.org/widget/clipboard;1"; const kClipboardIID = Components.interfaces.nsIClipboard; var clipboard = Components.classes[kClipboardContractID].getService(kClipboardIID); const kSuppArrayContractID = "@mozilla.org/supports-array;1"; const kSuppArrayIID = Components.interfaces.nsISupportsArray; var flavourArray = Components.classes[kSuppArrayContractID].createInstance(kSuppArrayIID); const kSuppStringContractID = "@mozilla.org/supports-cstring;1"; const kSuppStringIID = Components.interfaces.nsISupportsCString; var flavours = ["moz/bookmarkclipboarditem", "text/x-moz-url"]; for (i = 0; i < flavours.length; ++i) { const kSuppString = Components.classes[kSuppStringContractID].createInstance(kSuppStringIID); kSuppString.data = flavours[i]; flavourArray.AppendElement(kSuppString); } var hasFlavours = clipboard.hasDataMatchingFlavors(flavourArray, kClipboardIID.kGlobalClipboard); return hasFlavours; case "cmd_bm_copy": return length > 0; case "cmd_bm_cut": case "cmd_bm_delete": return length > 0 && aSelection.containsMutable && !aSelection.containsPTF; case "cmd_bm_selectAll": return true; case "cmd_bm_open": case "cmd_bm_expandfolder": case "cmd_bm_managefolder": return length == 1; case "cmd_bm_openinnewwindow": case "cmd_bm_openinnewtab": case "cmd_bm_find": case "cmd_bm_import": case "cmd_bm_export": return true; case "cmd_bm_newbookmark": case "cmd_bm_newfolder": case "cmd_bm_newseparator": return (aTarget && BookmarksUtils.isValidTargetContainer(aTarget.parent)); case "cmd_bm_properties": case "cmd_bm_rename": case "cmd_bm_sortfolderbyname": case "cmd_bm_sortfolder": return length == 1; case "cmd_bm_setnewbookmarkfolder": if (length != 1) return false; return item0 != "NC:NewBookmarkFolder" && (type0 == "Folder" || type0 == "PersonalToolbarFolder"); case "cmd_bm_setpersonaltoolbarfolder": if (length != 1) return false; return item0 != "NC:PersonalToolbarFolder" && item0 != "NC:BookmarksRoot" && type0 == "Folder"; case "cmd_bm_setnewsearchfolder": if (length != 1) return false; return item0 != "NC:NewSearchFolder" && (type0 == "Folder" || type0 == "PersonalToolbarFolder"); case "cmd_bm_movebookmark": return length > 0 && !aSelection.containsRF; default: return false; } }, doCommand: function (aCommand, aSelection, aTarget) { switch (aCommand) { case "cmd_undo": case "cmd_bm_undo": BookmarksCommand.undoBookmarkTransaction(); break; case "cmd_redo": case "cmd_bm_redo": BookmarksCommand.redoBookmarkTransaction(); break; case "cmd_bm_open": BookmarksCommand.openBookmark(aSelection, "current"); break; case "cmd_bm_openinnewwindow": BookmarksCommand.openBookmark(aSelection, "window"); break; case "cmd_bm_openinnewtab": BookmarksCommand.openBookmark(aSelection, "tab"); break; case "cmd_bm_managefolder": BookmarksCommand.manageFolder(aSelection); break; case "cmd_bm_setnewbookmarkfolder": case "cmd_bm_setpersonaltoolbarfolder": case "cmd_bm_setnewsearchfolder": BookmarksCommand.doBookmarksCommand(aSelection.item[0], NC_NS_CMD+aCommand.substring("cmd_bm_".length), []); break; case "cmd_bm_rename": case "cmd_bm_properties": BookmarksCommand.openBookmarkProperties(aSelection); break; case "cmd_bm_find": BookmarksCommand.findBookmark(); break; case "cmd_bm_cut": BookmarksCommand.cutBookmark(aSelection); break; case "cmd_bm_copy": BookmarksCommand.copyBookmark(aSelection); break; case "cmd_bm_paste": BookmarksCommand.pasteBookmark(aTarget); break; case "cmd_bm_delete": BookmarksCommand.deleteBookmark(aSelection); break; case "cmd_bm_movebookmark": BookmarksCommand.moveBookmark(aSelection); break; case "cmd_bm_newfolder": BookmarksCommand.createNewFolder(aTarget); break; case "cmd_bm_newbookmark": var folder = aTarget.parent.Value; var rv = { newBookmark: null }; openDialog("chrome://communicator/content/bookmarks/addBookmark.xul", "", "centerscreen,chrome,modal=yes,dialog=yes,resizable=yes", null, null, folder, null, "newBookmark", rv); break; case "cmd_bm_newseparator": BookmarksCommand.createNewSeparator(aTarget); break; case "cmd_bm_import": BookmarksCommand.importBookmarks(); break; case "cmd_bm_export": BookmarksCommand.exportBookmarks(); break; case "cmd_bm_sortfolderbyname": BookmarksCommand.sortFolderByName(aSelection); break; case "cmd_bm_sortfolder": BookmarksCommand.sortFolder(aSelection); break; default: dump("Bookmark command "+aCommand+" not handled!\n"); } }, onCommandUpdate: function (aSelection, aTarget) { var commands = ["cmd_bm_newbookmark", "cmd_bm_newfolder", "cmd_bm_newseparator", "cmd_bm_properties", "cmd_bm_rename", "cmd_bm_copy", "cmd_bm_paste", "cmd_bm_cut", "cmd_bm_delete", "cmd_bm_setpersonaltoolbarfolder", "cmd_bm_setnewbookmarkfolder", "cmd_bm_setnewsearchfolder", "cmd_bm_movebookmark", "cmd_bm_managefolder", "cmd_bm_sortfolder", "cmd_bm_sortfolderbyname", "cmd_undo", "cmd_redo", "cmd_bm_undo", "cmd_bm_redo"]; for (var i = 0; i < commands.length; ++i) { var commandNode = document.getElementById(commands[i]); if (commandNode) { if (this.isCommandEnabled(commands[i], aSelection, aTarget)) commandNode.removeAttribute("disabled"); else commandNode.setAttribute("disabled", "true"); } } } } function CommandArrayEnumerator (aCommandArray) { this._inner = []; for (var i = 0; i < aCommandArray.length; ++i) this._inner.push(RDF.GetResource(NC_NS_CMD + aCommandArray[i])); this._index = 0; } CommandArrayEnumerator.prototype = { getNext: function () { return this._inner[this._index]; }, hasMoreElements: function () { return this._index < this._inner.length; } }; var BookmarksUtils = { DROP_BEFORE: Components.interfaces.nsITreeView.DROP_BEFORE, DROP_ON : Components.interfaces.nsITreeView.DROP_ON, DROP_AFTER : Components.interfaces.nsITreeView.DROP_AFTER, any: function (aArray) { for (var i=0; i see bug 63370 for details var LOCALESVC = Components.classes["@mozilla.org/intl/nslocaleservice;1"] .getService(Components.interfaces.nsILocaleService); var BUNDLESVC = Components.classes["@mozilla.org/intl/stringbundle;1"] .getService(Components.interfaces.nsIStringBundleService); var bookmarksBundle = "chrome://communicator/locale/bookmarks/bookmarks.properties"; this._bundle = BUNDLESVC.createBundle(bookmarksBundle, LOCALESVC.getApplicationLocale()); var brandBundle = "chrome://branding/locale/brand.properties"; this._brandShortName = BUNDLESVC.createBundle(brandBundle, LOCALESVC.getApplicationLocale()) .GetStringFromName("brandShortName"); } var bundle; try { if (!aReplaceString) bundle = this._bundle.GetStringFromName(aStringKey); else if (typeof(aReplaceString) == "string") bundle = this._bundle.formatStringFromName(aStringKey, [aReplaceString], 1); else bundle = this._bundle.formatStringFromName(aStringKey, aReplaceString, aReplaceString.length); } catch (e) { dump("Bookmark bundle "+aStringKey+" not found!\n"); bundle = ""; } bundle = bundle.replace(/%brandShortName%/, this._brandShortName); return bundle; }, ///////////////////////////////////////////////////////////////////////////// // returns the literal targeted by the URI aArcURI for a resource or uri getProperty: function (aInput, aArcURI, aDS) { var node; var arc = RDF.GetResource(aArcURI); if (typeof(aInput) == "string") aInput = RDF.GetResource(aInput); if (!aDS) node = BMDS.GetTarget(aInput, arc, true); else node = aDS .GetTarget(aInput, arc, true); return (node instanceof kRDFRSCIID) || (node instanceof kRDFLITIID) ? node.Value : ""; }, getResource: function (aName) { if (aName == "LastModifiedDate" || aName == "LastVisitDate") { return RDF.GetResource(WEB_NS + aName); } else { return RDF.GetResource(NC_NS + aName); } }, ///////////////////////////////////////////////////////////////////////////// // Determine the rdf:type property for the given resource. resolveType: function (aResource) { var type = this.getProperty(aResource, RDF_NS+"type"); if (type != "") type = type.split("#")[1]; if (type == "Folder") { if (this.isPersonalToolbarFolder(aResource)) type = "PersonalToolbarFolder"; else if (this.isFolderGroup(aResource)) type = "FolderGroup"; } return type; }, ///////////////////////////////////////////////////////////////////////////// // Returns true if aResource is a folder group isFolderGroup: function (aResource) { return this.getProperty(aResource, NC_NS+"FolderGroup") == "true"; }, ///////////////////////////////////////////////////////////////////////////// // Returns true if aResource is the Personal Toolbar Folder isPersonalToolbarFolder: function (aResource) { return this.getProperty(aResource, NC_NS+"FolderType") == "NC:PersonalToolbarFolder"; }, ///////////////////////////////////////////////////////////////////////////// // Returns the folder which 'FolderType' is aProperty getSpecialFolder: function (aProperty) { var sources = BMDS.GetSources(RDF.GetResource(NC_NS+"FolderType"), RDF.GetResource(aProperty), true); var folder = null; if (sources.hasMoreElements()) folder = sources.getNext(); else folder = RDF.GetResource("NC:BookmarksRoot"); return folder; }, ///////////////////////////////////////////////////////////////////////////// // Returns the New Bookmark Folder getNewBookmarkFolder: function() { return this.getSpecialFolder("NC:NewBookmarkFolder"); }, ///////////////////////////////////////////////////////////////////////////// // Returns the New Search Folder getNewSearchFolder: function() { return this.getSpecialFolder("NC:NewSearchFolder"); }, ///////////////////////////////////////////////////////////////////////////// // Returns the container of a given container getParentOfContainer: function(aChild) { var arcsIn = BMDS.ArcLabelsIn(aChild); var containerArc; while (arcsIn.hasMoreElements()) { containerArc = arcsIn.getNext(); if (RDFCU.IsOrdinalProperty(containerArc)) { return BMDS.GetSources(containerArc, aChild, true).getNext() .QueryInterface(kRDFRSCIID); } } return null; }, ///////////////////////////////////////////////////////////////////////////// // Caches frequently used informations about the selection checkSelection: function (aSelection) { if (aSelection.length == 0) return; aSelection.type = new Array(aSelection.length); aSelection.protocol = new Array(aSelection.length); aSelection.isContainer = new Array(aSelection.length); aSelection.isImmutable = new Array(aSelection.length); aSelection.isValid = new Array(aSelection.length); aSelection.containsMutable = false; aSelection.containsPTF = false; aSelection.containsRF = false; var index, item, parent, type, protocol, isContainer, isImmutable, isValid; for (var i=0; i"+itemName+""); data.addDataForFlavour("text/unicode", itemUrl); dataSet.push(data); } return dataSet; }, getSelectionFromXferData: function (aDragSession) { var selection = {}; selection.item = []; selection.parent = []; var trans = Components.classes["@mozilla.org/widget/transferable;1"] .createInstance(Components.interfaces.nsITransferable); trans.addDataFlavor("moz/rdfitem"); trans.addDataFlavor("text/x-moz-url"); trans.addDataFlavor("text/unicode"); var uri, extra, rSource, rParent, parent; for (var i = 0; i < aDragSession.numDropItems; ++i) { var bestFlavour = {}, dataObj = {}, len = {}; aDragSession.getData(trans, i); trans.getAnyTransferData(bestFlavour, dataObj, len); dataObj = dataObj.value.QueryInterface(Components.interfaces.nsISupportsString); if (!dataObj) continue; dataObj = dataObj.data.substring(0, len.value).split("\n"); uri = dataObj[0]; if (dataObj.length > 1 && dataObj[1] != "") extra = dataObj[1]; else extra = null; switch (bestFlavour.value) { case "moz/rdfitem": rSource = RDF.GetResource(uri); parent = extra; break; case "text/x-moz-url": case "text/unicode": rSource = BookmarksUtils.createBookmark(null, uri, null, extra); parent = null; break; } selection.item.push(rSource); if (parent) rParent = RDF.GetResource(parent); else rParent = null; selection.parent.push(rParent); } selection.length = selection.item.length; BookmarksUtils.checkSelection(selection); return selection; }, getTargetFromFolder: function(aResource) { var index = parseInt(this.getProperty(aResource, RDF_NS+"nextVal")); if (isNaN(index)) return {parent: null, index: -1}; else return {parent: aResource, index: index}; }, getSelectionFromResource: function (aItem, aParent) { var selection = {}; selection.length = 1; selection.item = [aItem ]; selection.parent = [aParent]; this.checkSelection(selection); return selection; }, createBookmark: function (aName, aURL, aCharSet, aDefaultName) { if (!aName) { // look up in the history ds to retrieve the name var rSource = RDF.GetResource(aURL); var HISTDS = RDF.GetDataSource("rdf:history"); var nameArc = RDF.GetResource(NC_NS+"Name"); var rName = HISTDS.GetTarget(rSource, nameArc, true); aName = rName ? rName.QueryInterface(kRDFLITIID).Value : aDefaultName; if (!aName) aName = aURL; } if (!aCharSet) { var fw = document.commandDispatcher.focusedWindow; if (fw) aCharSet = fw.document.characterSet; } return BMSVC.createBookmark(aName, aURL, null, null, aCharSet); }, flushDataSource: function () { var remoteDS = BMDS.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource); setTimeout(function () {remoteDS.Flush()}, 100); }, addBookmarkForTabBrowser: function( aTabBrowser, aSelect ) { var tabsInfo = []; var currentTabInfo = { name: "", url: "", charset: null }; const activeBrowser = aTabBrowser.selectedBrowser; const browsers = aTabBrowser.browsers; for (var i = 0; i < browsers.length; ++i) { var webNav = browsers[i].webNavigation; var url = webNav.currentURI.spec; var name = ""; var charset; try { name = webNav.document.title || url; charset = webNav.document.characterSet; } catch (e) { name = url; } tabsInfo[i] = { name: name, url: url, charset: charset }; if (browsers[i] == activeBrowser) currentTabInfo = tabsInfo[i]; } openDialog("chrome://communicator/content/bookmarks/addBookmark.xul", "", "centerscreen,chrome,dialog=yes,resizable=yes,dependent", currentTabInfo.name, currentTabInfo.url, null, currentTabInfo.charset, "addGroup" + (aSelect ? ",group" : ""), tabsInfo); }, addBookmarkForBrowser: function (aDocShell, aShowDialog) { // Bug 52536: We obtain the URL and title from the nsIWebNavigation // associated with a rather than from a DOMWindow. // This is because when a full page plugin is loaded, there is // no DOMWindow (?) but information about the loaded document // may still be obtained from the webNavigation. var uri = aDocShell.currentURI; if (uri.schemeIs("javascript") || uri.schemeIs("data")) aShowDialog = true; var url = uri.spec; var title, docCharset = null; try { title = aDocShell.document.title || url; docCharset = aDocShell.document.characterSet; } catch (e) { title = url; } this.addBookmark(url, title, docCharset, aShowDialog); }, // should update the caller, aShowDialog is no more necessary addBookmark: function (aURL, aTitle, aCharset, aShowDialog) { if (aCharset === undefined) { var fw = document.commandDispatcher.focusedWindow; aCharset = fw.document.characterSet; } if (aShowDialog) { openDialog("chrome://communicator/content/bookmarks/addBookmark.xul", "", "centerscreen,chrome,dialog=yes,resizable=yes,dependent", aTitle, aURL, null, aCharset); } else { // User has elected to override the file dialog and always file bookmarks // into the default bookmark folder. BMSVC.addBookmarkImmediately(aURL, aTitle, kBMSVCIID.BOOKMARK_DEFAULT_TYPE, aCharset); } }, shouldLoadTabInBackground: function(aEvent) { var loadInBackground = PREF.getBoolPref("browser.tabs.loadInBackground"); if (aEvent.shiftKey) loadInBackground = !loadInBackground; return loadInBackground; }, getBrowserTargetFromEvent: function (aEvent) { if (!aEvent) return null; gLoadInBackground = this.shouldLoadTabInBackground(aEvent); switch (aEvent.type) { case "click": case "dblclick": if (aEvent.button > 1) return null; // Prevent default click handling (e.g. middlemouse.contentLoadURL==true) aEvent.preventDefault(); if (aEvent.button != 1 && !aEvent.metaKey && !aEvent.ctrlKey) return "current"; break; case "keypress": case "command": if (!aEvent.metaKey && !aEvent.ctrlKey) return "current"; break; default: return null; } if (PREF && PREF.getBoolPref("browser.tabs.opentabfor.middleclick")) return "tab"; if (PREF && PREF.getBoolPref("middlemouse.openNewWindow")) return "window"; return null; }, loadBookmarkBrowser: function (aEvent, aDS) { var target = BookmarksUtils.getBrowserTargetFromEvent(aEvent); if (!target) return; var rSource = RDF.GetResource(aEvent.target.id); var selection = BookmarksUtils.getSelectionFromResource(rSource); BookmarksCommand.openBookmark(selection, target, aDS) } } function BookmarkTransaction() { } BookmarkTransaction.prototype = { BATCH_LIMIT : 8, RDFC : null, BMDS : null, beginUpdateBatch: function() { if (this.item.length > this.BATCH_LIMIT) { this.BMDS.beginUpdateBatch(); } }, endUpdateBatch: function() { if (this.item.length > this.BATCH_LIMIT) { this.BMDS.endUpdateBatch(); } }, // nsITransaction method stubs doTransaction: function() {}, undoTransaction: function() {}, redoTransaction: function() { this.doTransaction(); }, get isTransient() { return false; }, merge: function(aTransaction) { return false; }, // debugging helper get wrappedJSObject() { return this; } } function BookmarkInsertTransaction (aAction) { this.type = "insert"; this.action = aAction; this.item = null; this.parent = null; this.index = null; this.isValid = null; } BookmarkInsertTransaction.prototype = { __proto__: BookmarkTransaction.prototype, doTransaction: function () { this.beginUpdateBatch(); for (var i=0; i=0; i--) { if (this.isValid[i]) { container.Init(this.BMDS, this.parent[i]); container.RemoveElementAt(this.index[i], true); } } this.endUpdateBatch(); } } function BookmarkRemoveTransaction (aAction) { this.type = "remove"; this.action = aAction; this.item = null; this.parent = null; this.index = null; this.isValid = null; } BookmarkRemoveTransaction.prototype = { __proto__: BookmarkTransaction.prototype, doTransaction: function () { this.beginUpdateBatch(); for (var i=0; i=0; i--) { if (this.isValid[i]) { this.RDFC.Init(this.BMDS, this.parent[i]); this.RDFC.InsertElementAt(this.item[i], this.index[i], false); } } this.endUpdateBatch(); } } function BookmarkMoveTransaction (aAction, aSelection, aTarget) { this.type = "move"; this.action = aAction; this.selection = aSelection; this.target = aTarget; this.isValid = aSelection.isValid; } BookmarkMoveTransaction.prototype = { __proto__: BookmarkTransaction.prototype, beginUpdateBatch: function() { if (this.selection.length > this.BATCH_LIMIT) { this.BMDS.beginUpdateBatch(); } }, endUpdateBatch: function() { if (this.selection.length > this.BATCH_LIMIT) { this.BMDS.endUpdateBatch(); } }, doTransaction: function () { this.beginUpdateBatch(); BookmarksUtils.removeSelection("move", this.selection); BookmarksUtils.insertSelection("move", this.selection, this.target); this.endUpdateBatch(); }, redoTransaction : function () {} } function BookmarkImportTransaction (aAction) { this.type = "import"; this.action = aAction; this.item = []; this.parent = []; this.index = []; this.isValid = []; } BookmarkImportTransaction.prototype = { __proto__: BookmarkTransaction.prototype, undoTransaction: function () { this.beginUpdateBatch(); for (var i=this.item.length-1; i>=0; i--) { if (this.isValid[i]) { this.RDFC.Init(this.BMDS, this.parent[i]); this.RDFC.RemoveElementAt(this.index[i], true); } } this.endUpdateBatch(); }, redoTransaction: function () { this.beginUpdateBatch(); for (var i=0; i