home *** CD-ROM | disk | FTP | other *** search
/ Chip 2008 June / CHIP-2008-06.iso / bonus / +10SecurityTips / files / xB-Browser_2.0.0.12b.exe / App / Browser / firefox / components / nsBookmarkTransactionManager.js < prev    next >
Encoding:
JavaScript  |  2008-02-02  |  13.6 KB  |  377 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3.  *
  4.  * The contents of this file are subject to the Mozilla Public License Version
  5.  * 1.1 (the "License"); you may not use this file except in compliance with
  6.  * the License. You may obtain a copy of the License at
  7.  * http://www.mozilla.org/MPL/
  8.  *
  9.  * Software distributed under the License is distributed on an "AS IS" basis,
  10.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11.  * for the specific language governing rights and limitations under the
  12.  * License.
  13.  *
  14.  * The Original Code is bookmark transaction code.
  15.  *
  16.  * The Initial Developer of the Original Code is
  17.  *   Joey Minta <jminta@gmail.com>
  18.  *
  19.  * Portions created by the Initial Developer are Copyright (C) 2006
  20.  * the Initial Developer. All Rights Reserved.
  21.  *
  22.  * Contributor(s):
  23.  *
  24.  * Alternatively, the contents of this file may be used under the terms of
  25.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  26.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27.  * in which case the provisions of the GPL or the LGPL are applicable instead
  28.  * of those above. If you wish to allow use of your version of this file only
  29.  * under the terms of either the GPL or the LGPL, and not to allow others to
  30.  * use your version of this file under the terms of the MPL, indicate your
  31.  * decision by deleting the provisions above and replace them with the notice
  32.  * and other provisions required by the GPL or the LGPL. If you do not delete
  33.  * the provisions above, a recipient may use your version of this file under
  34.  * the terms of any one of the MPL, the GPL or the LGPL.
  35.  *
  36.  * ***** END LICENSE BLOCK ***** */
  37.  
  38. function bookmarkTransactionManager() {
  39.     this.wrappedJSObject = this;
  40.     this.mTransactionManager = Components.classes["@mozilla.org/transactionmanager;1"]
  41.                                          .createInstance(Components.interfaces.nsITransactionManager);
  42.  
  43.     this.mBatchCount = 0;
  44.  
  45.     this.classInfo = {
  46.         getInterfaces: function (count) {
  47.             var ifaces = [
  48.                 Components.interfaces.nsISupports,
  49.                 Components.interfaces.nsIClassInfo
  50.             ];
  51.             count.value = ifaces.length;
  52.             return ifaces;
  53.         },
  54.  
  55.         getHelperForLanguage: function (language) {
  56.             return null;
  57.         },
  58.  
  59.         contractID: "@mozilla.org/bookmarks/transactionManager;1",
  60.         classDescription: "Booksmarks Transaction Manager",
  61.         classID: Components.ID("{62d2f7fb-acd2-4876-aa2d-b607de9329ff}"),
  62.         implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
  63.         flags: 0
  64.     };
  65.  
  66.     // Define our transactions
  67.     function bkmkTxn() {
  68.         this.item    = null;
  69.         this.parent  = null;
  70.         this.index   = null;
  71.         this.removedProp = null;
  72.     };
  73.  
  74.     bkmkTxn.prototype = {
  75.         BMDS: null,
  76.  
  77.         QueryInterface: function bkmkTxnQI(iid) {
  78.             if (!iid.equals(Components.interfaces.nsITransaction) &&
  79.                 !iid.equals(Components.interfaces.nsISupports))
  80.             throw Components.results.NS_ERROR_NO_INTERFACE;
  81.  
  82.             return this;
  83.         },
  84.  
  85.         merge               : function (aTxn)   {return false},
  86.         getHelperForLanguage: function (aCount) {return null},
  87.         getInterfaces       : function (aCount) {return null},
  88.         canCreateWrapper    : function (aIID)   {return "AllAccess"},
  89.  
  90.         mAssertProperties: function bkmkTxnAssertProps(aProps) {
  91.             if (!aProps) {
  92.                 return;
  93.             }
  94.  
  95.             for each (var prop in aProps) {
  96.                 for (var i = 0; i < this.Properties.length; i++) {
  97.                     var oldValue = this.BMDS.GetTarget(this.item, this.Properties[i], true);
  98.                     // must check, if paste call after copy the oldvalue didn't remove.
  99.                     if (!oldValue) {
  100.                         var newValue = aProps[i];
  101.                         if (newValue) {
  102.                             this.BMDS.Assert(this.item, 
  103.                                              this.Properties[i], 
  104.                                              newValue, true);
  105.                         }
  106.                     } else {
  107.                         this.removedProp[i] = oldValue;
  108.                     }
  109.                 }
  110.             }
  111.         },
  112.  
  113.         mUnassertProperties: function bkmkTxnUnassertProps(aProps) {
  114.             if (!aProps) {
  115.                 return;
  116.             }
  117.             for each (var prop in aProps) {
  118.                 for (var i = 0; i < this.Properties.length; i++) {
  119.                     var oldValue = aProps[i];
  120.                     if (oldValue) {
  121.                         this.BMDS.Unassert(this.item, this.Properties[i], oldValue);
  122.                     }
  123.                 }
  124.             }
  125.         }
  126.     };
  127.  
  128.     bkmkTxn.prototype.RDFC = 
  129.             Components.classes["@mozilla.org/rdf/container;1"]
  130.                       .createInstance(Components.interfaces.nsIRDFContainer);
  131.     var rdfService = Components.classes["@mozilla.org/rdf/rdf-service;1"]
  132.                                .getService(Components.interfaces.nsIRDFService);
  133.     bkmkTxn.prototype.BMDS = rdfService.GetDataSource("rdf:bookmarks");
  134.  
  135.     bkmkTxn.prototype.Properties = 
  136.             [rdfService.GetResource("http://home.netscape.com/NC-rdf#Name"),
  137.              rdfService.GetResource("http://home.netscape.com/NC-rdf#URL"),
  138.              rdfService.GetResource("http://home.netscape.com/NC-rdf#ShortcutURL"),
  139.              rdfService.GetResource("http://home.netscape.com/NC-rdf#Description"),
  140.              rdfService.GetResource("http://home.netscape.com/NC-rdf#WebPanel"),
  141.              rdfService.GetResource("http://home.netscape.com/NC-rdf#FeedURL"),
  142.              rdfService.GetResource("http://home.netscape.com/NC-rdf#MicsumGenURI"),
  143.              rdfService.GetResource("http://home.netscape.com/NC-rdf#MicsumExpiration"),
  144.              rdfService.GetResource("http://home.netscape.com/NC-rdf#GeneratedTitle")];
  145.  
  146.     function bkmkInsertTxn(aAction) {
  147.         this.type = "insert";
  148.         // move container declaration to here so it can be recognized if
  149.         // undoTransaction is call after the BM manager is close and reopen.
  150.         this.container = Components.classes["@mozilla.org/rdf/container;1"]
  151.                                    .createInstance(Components.interfaces.nsIRDFContainer);
  152.     }
  153.  
  154.     bkmkInsertTxn.prototype = {
  155.          __proto__: bkmkTxn.prototype,
  156.  
  157.          isTransient: false,
  158.  
  159.          doTransaction: function bkmkInsertDoTxn() {
  160.              this.RDFC.Init(this.BMDS, this.parent);
  161.              // if the index is -1, we use appendElement, and then update the
  162.              // index so that undoTransaction can still function
  163.              if (this.index == -1) {
  164.                  this.RDFC.AppendElement(this.item);
  165.                  this.index = this.RDFC.GetCount();
  166.              } else {
  167. /*XXX- broken insert code, see bug 264571
  168.                  try {
  169.                      this.RDFC.InsertElementAt(this.item, this.index, true);
  170.                  } catch (e if e.result == Components.results.NS_ERROR_ILLEGAL_VALUE) {
  171.                      // if this failed, then we assume that we really want to append,
  172.                      // because things are out of whack until we renumber.
  173.                      this.RDFC.AppendElement(this.item);
  174.                      // and then fix up the index so undo works
  175.                      this.index = this.RDFC.GetCount();
  176.                  }
  177. */
  178.                  this.RDFC.InsertElementAt(this.item, this.index, true);
  179.              }
  180.  
  181.              // insert back all the properties
  182.              this.mAssertProperties(this.removedProp);
  183.          },
  184.  
  185.          undoTransaction: function bkmkInsertUndoTxn() {
  186.              // XXXvarga Can't use |RDFC| here because it's being "reused" elsewhere.
  187.              this.container.Init(this.BMDS, this.parent);
  188.  
  189.              // remove all properties befor we remove the element so
  190.              // nsLocalSearchService doesn't return deleted element in Search
  191.              this.mUnassertProperties(this.removedProp);
  192.  
  193.              this.container.RemoveElementAt(this.index, true);
  194.          },
  195.  
  196.          redoTransaction: function bkmkInsertRedoTxn() {
  197.              this.doTransaction();
  198.          }
  199.     };
  200.  
  201.     function bkmkRemoveTxn() {
  202.         this.type    = "remove";
  203.     }
  204.  
  205.     bkmkRemoveTxn.prototype = {
  206.         __proto__: bkmkTxn.prototype,
  207.  
  208.         isTransient: false,
  209.  
  210.         doTransaction: function bkmkRemoveDoTxn() {
  211.             this.RDFC.Init(this.BMDS, this.parent);
  212.  
  213.             // remove all properties befor we remove the element so
  214.             // nsLocalSearchService doesn't return deleted element in Search
  215.             this.mUnassertProperties(this.removedProp);
  216.  
  217.             this.RDFC.RemoveElementAt(this.index, false);
  218.         },
  219.  
  220.         undoTransaction: function bkmkRemoveUndoTxn() {
  221.             this.RDFC.Init(this.BMDS, this.parent);
  222.             this.RDFC.InsertElementAt(this.item, this.index, false);
  223.  
  224.             // insert back all the properties
  225.             this.mAssertProperties(this.removedProp);
  226.         },
  227.  
  228.         redoTransaction: function () {
  229.             this.doTransaction();
  230.         }
  231.     }
  232.  
  233.     function bkmkImportTxn(aAction) {
  234.         this.type    = "import";
  235.         this.action  = aAction;
  236.     }
  237.  
  238.     bkmkImportTxn.prototype = {
  239.         __proto__: bkmkTxn.prototype,
  240.  
  241.         isTransient: false,
  242.  
  243.         doTransaction: function bkmkImportDoTxn() {},
  244.  
  245.         undoTransaction: function mkmkImportUndoTxn() {
  246.             this.RDFC.Init(this.BMDS, this.parent);
  247.             this.RDFC.RemoveElementAt(this.index, true);
  248.         },
  249.  
  250.         redoTransaction: function bkmkImportredoTxn() {
  251.             this.RDFC.Init(this.BMDS, this.parent);
  252.             this.RDFC.InsertElementAt(this.item, this.index, true);
  253.         }
  254.     };
  255.  
  256.     this.BookmarkRemoveTransaction = bkmkRemoveTxn;
  257.     this.BookmarkInsertTransaction = bkmkInsertTxn;
  258.     this.BookmarkImportTransaction = bkmkImportTxn;
  259. }
  260.  
  261. bookmarkTransactionManager.prototype.QueryInterface = function bkTxnMgrQI(aIID) {
  262.     if (aIID.equals(Components.interfaces.nsISupports) ||
  263.         aIID.equals(Components.interfaces.nsIBookmarkTransactionManager)) {
  264.         return this;
  265.     } 
  266.     if (aIID.equals(Components.interfaces.nsIClassInfo)) {
  267.         return this.classInfo;
  268.     }
  269.  
  270.     throw NS_ERROR_NO_INTERFACE;
  271. }
  272.  
  273. bookmarkTransactionManager.prototype.createAndCommitTxn = 
  274. function bkmkTxnMgrCandC(aType, aAction, aItem, aIndex, aParent, aPropCount, aRemovedProps) {
  275.     var txn;
  276.     var nsIBookmarkTransactionManager = Components.interfaces.nsIBookmarkTransactionManager;
  277.     switch (aType) {
  278.         case nsIBookmarkTransactionManager.IMPORT: 
  279.             txn = new this.BookmarkImportTransaction(aAction);
  280.             break;
  281.         case nsIBookmarkTransactionManager.INSERT: 
  282.             txn = new this.BookmarkInsertTransaction(aAction);
  283.             break;
  284.         case nsIBookmarkTransactionManager.REMOVE: 
  285.             txn = new this.BookmarkRemoveTransaction(aAction);
  286.             break;
  287.         default:
  288.             Components.utils.reportError("Unknown bookmark transaction type:"+aType);
  289.             throw NS_ERROR_FAILURE;
  290.     }
  291.     txn.item = aItem;
  292.     txn.parent = aParent;
  293.     txn.index = aIndex;
  294.     txn.removedProp = aRemovedProps;
  295.     txn.action = aAction;
  296.     txn.wrappedJSObject = txn;
  297.     this.mTransactionManager.doTransaction(txn);
  298. }
  299.  
  300. bookmarkTransactionManager.prototype.startBatch = function bkmkTxnMgrUndo() {
  301.     if (this.mBatchCount == 0) {
  302.         this.mTransactionManager.beginBatch();
  303.     }
  304.     this.mBatchCount++;
  305. }
  306.  
  307. bookmarkTransactionManager.prototype.endBatch = function bkmkTxnMgrUndo() {
  308.     this.mBatchCount--;
  309.     if (this.mBatchCount == 0) {
  310.         this.mTransactionManager.endBatch();
  311.     }
  312. }
  313.  
  314. bookmarkTransactionManager.prototype.undo = function bkmkTxnMgrUndo() {
  315.     this.mTransactionManager.undoTransaction();
  316. }
  317.  
  318. bookmarkTransactionManager.prototype.redo = function bkmkTxnMgrRedo() {
  319.     this.mTransactionManager.redoTransaction();
  320. }
  321.  
  322. bookmarkTransactionManager.prototype.canUndo = function bkmkTxnMgrCanUndo() {
  323.     return this.mTransactionManager.numberOfUndoItems > 0;
  324. }
  325.  
  326. bookmarkTransactionManager.prototype.canRedo = function bkmkTxnMgrCanRedo() {
  327.     return this.mTransactionManager.numberOfRedoItems > 0;
  328. }
  329.  
  330. bookmarkTransactionManager.prototype.__defineGetter__("transactionManager", 
  331. function bkmkTxnMgrGetter() {  return this.mTransactionManager; });
  332.  
  333. /****
  334.  **** module registration
  335.  ****/
  336.  
  337. const kFactory = {
  338.     createInstance: function (outer, iid) {
  339.         if (outer != null)
  340.             throw Components.results.NS_ERROR_NO_AGGREGATION;
  341.         return (new bookmarkTransactionManager()).QueryInterface(iid);
  342.     }
  343. };
  344.  
  345. var bkmkTxnMgrModule = {
  346.     mCID: Components.ID("{8be133d0-681d-4f0b-972b-6a68e41afb62}"),
  347.     mContractID: "@mozilla.org/bookmarks/transactionmanager;1",
  348.     
  349.     registerSelf: function (compMgr, fileSpec, location, type) {
  350.         compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  351.         compMgr.registerFactoryLocation(this.mCID,
  352.                                         "Bookmark Transaction Manager",
  353.                                         this.mContractID,
  354.                                         fileSpec,
  355.                                         location,
  356.                                         type);
  357.     },
  358.  
  359.     getClassObject: function (compMgr, cid, iid) {
  360.         if (!cid.equals(this.mCID))
  361.             throw Components.results.NS_ERROR_NO_INTERFACE;
  362.  
  363.         if (!iid.equals(Components.interfaces.nsIFactory))
  364.             throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  365.  
  366.         return kFactory;
  367.     },
  368.  
  369.     canUnload: function(compMgr) {
  370.         return true;
  371.     }
  372. };
  373.  
  374. function NSGetModule(compMgr, fileSpec) {
  375.     return bkmkTxnMgrModule;
  376. }
  377.