services/sync/modules/engines/forms.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 this.EXPORTED_SYMBOLS = ['FormEngine', 'FormRec'];
michael@0 6
michael@0 7 const Cc = Components.classes;
michael@0 8 const Ci = Components.interfaces;
michael@0 9 const Cu = Components.utils;
michael@0 10
michael@0 11 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
michael@0 12 Cu.import("resource://services-sync/engines.js");
michael@0 13 Cu.import("resource://services-sync/record.js");
michael@0 14 Cu.import("resource://services-common/async.js");
michael@0 15 Cu.import("resource://services-sync/util.js");
michael@0 16 Cu.import("resource://services-sync/constants.js");
michael@0 17 Cu.import("resource://gre/modules/Log.jsm");
michael@0 18
michael@0 19 const FORMS_TTL = 5184000; // 60 days
michael@0 20
michael@0 21 this.FormRec = function FormRec(collection, id) {
michael@0 22 CryptoWrapper.call(this, collection, id);
michael@0 23 }
michael@0 24 FormRec.prototype = {
michael@0 25 __proto__: CryptoWrapper.prototype,
michael@0 26 _logName: "Sync.Record.Form",
michael@0 27 ttl: FORMS_TTL
michael@0 28 };
michael@0 29
michael@0 30 Utils.deferGetSet(FormRec, "cleartext", ["name", "value"]);
michael@0 31
michael@0 32
michael@0 33 let FormWrapper = {
michael@0 34 _log: Log.repository.getLogger("Sync.Engine.Forms"),
michael@0 35
michael@0 36 _getEntryCols: ["fieldname", "value"],
michael@0 37 _guidCols: ["guid"],
michael@0 38
michael@0 39 // Do a "sync" search by spinning the event loop until it completes.
michael@0 40 _searchSpinningly: function(terms, searchData) {
michael@0 41 let results = [];
michael@0 42 let cb = Async.makeSpinningCallback();
michael@0 43 let callbacks = {
michael@0 44 handleResult: function(result) {
michael@0 45 results.push(result);
michael@0 46 },
michael@0 47 handleCompletion: function(reason) {
michael@0 48 cb(null, results);
michael@0 49 }
michael@0 50 };
michael@0 51 Svc.FormHistory.search(terms, searchData, callbacks);
michael@0 52 return cb.wait();
michael@0 53 },
michael@0 54
michael@0 55 _updateSpinningly: function(changes) {
michael@0 56 if (!Svc.FormHistory.enabled) {
michael@0 57 return; // update isn't going to do anything.
michael@0 58 }
michael@0 59 let cb = Async.makeSpinningCallback();
michael@0 60 let callbacks = {
michael@0 61 handleCompletion: function(reason) {
michael@0 62 cb();
michael@0 63 }
michael@0 64 };
michael@0 65 Svc.FormHistory.update(changes, callbacks);
michael@0 66 return cb.wait();
michael@0 67 },
michael@0 68
michael@0 69 getEntry: function (guid) {
michael@0 70 let results = this._searchSpinningly(this._getEntryCols, {guid: guid});
michael@0 71 if (!results.length) {
michael@0 72 return null;
michael@0 73 }
michael@0 74 return {name: results[0].fieldname, value: results[0].value};
michael@0 75 },
michael@0 76
michael@0 77 getGUID: function (name, value) {
michael@0 78 // Query for the provided entry.
michael@0 79 let query = { fieldname: name, value: value };
michael@0 80 let results = this._searchSpinningly(this._guidCols, query);
michael@0 81 return results.length ? results[0].guid : null;
michael@0 82 },
michael@0 83
michael@0 84 hasGUID: function (guid) {
michael@0 85 // We could probably use a count function here, but searchSpinningly exists...
michael@0 86 return this._searchSpinningly(this._guidCols, {guid: guid}).length != 0;
michael@0 87 },
michael@0 88
michael@0 89 replaceGUID: function (oldGUID, newGUID) {
michael@0 90 let changes = {
michael@0 91 op: "update",
michael@0 92 guid: oldGUID,
michael@0 93 newGuid: newGUID,
michael@0 94 }
michael@0 95 this._updateSpinningly(changes);
michael@0 96 }
michael@0 97
michael@0 98 };
michael@0 99
michael@0 100 this.FormEngine = function FormEngine(service) {
michael@0 101 SyncEngine.call(this, "Forms", service);
michael@0 102 }
michael@0 103 FormEngine.prototype = {
michael@0 104 __proto__: SyncEngine.prototype,
michael@0 105 _storeObj: FormStore,
michael@0 106 _trackerObj: FormTracker,
michael@0 107 _recordObj: FormRec,
michael@0 108 applyIncomingBatchSize: FORMS_STORE_BATCH_SIZE,
michael@0 109
michael@0 110 get prefName() "history",
michael@0 111
michael@0 112 _findDupe: function _findDupe(item) {
michael@0 113 return FormWrapper.getGUID(item.name, item.value);
michael@0 114 }
michael@0 115 };
michael@0 116
michael@0 117 function FormStore(name, engine) {
michael@0 118 Store.call(this, name, engine);
michael@0 119 }
michael@0 120 FormStore.prototype = {
michael@0 121 __proto__: Store.prototype,
michael@0 122
michael@0 123 _processChange: function (change) {
michael@0 124 // If this._changes is defined, then we are applying a batch, so we
michael@0 125 // can defer it.
michael@0 126 if (this._changes) {
michael@0 127 this._changes.push(change);
michael@0 128 return;
michael@0 129 }
michael@0 130
michael@0 131 // Otherwise we must handle the change synchronously, right now.
michael@0 132 FormWrapper._updateSpinningly(change);
michael@0 133 },
michael@0 134
michael@0 135 applyIncomingBatch: function (records) {
michael@0 136 // We collect all the changes to be made then apply them all at once.
michael@0 137 this._changes = [];
michael@0 138 let failures = Store.prototype.applyIncomingBatch.call(this, records);
michael@0 139 if (this._changes.length) {
michael@0 140 FormWrapper._updateSpinningly(this._changes);
michael@0 141 }
michael@0 142 delete this._changes;
michael@0 143 return failures;
michael@0 144 },
michael@0 145
michael@0 146 getAllIDs: function () {
michael@0 147 let results = FormWrapper._searchSpinningly(["guid"], [])
michael@0 148 let guids = {};
michael@0 149 for (let result of results) {
michael@0 150 guids[result.guid] = true;
michael@0 151 }
michael@0 152 return guids;
michael@0 153 },
michael@0 154
michael@0 155 changeItemID: function (oldID, newID) {
michael@0 156 FormWrapper.replaceGUID(oldID, newID);
michael@0 157 },
michael@0 158
michael@0 159 itemExists: function (id) {
michael@0 160 return FormWrapper.hasGUID(id);
michael@0 161 },
michael@0 162
michael@0 163 createRecord: function (id, collection) {
michael@0 164 let record = new FormRec(collection, id);
michael@0 165 let entry = FormWrapper.getEntry(id);
michael@0 166 if (entry != null) {
michael@0 167 record.name = entry.name;
michael@0 168 record.value = entry.value;
michael@0 169 } else {
michael@0 170 record.deleted = true;
michael@0 171 }
michael@0 172 return record;
michael@0 173 },
michael@0 174
michael@0 175 create: function (record) {
michael@0 176 this._log.trace("Adding form record for " + record.name);
michael@0 177 let change = {
michael@0 178 op: "add",
michael@0 179 fieldname: record.name,
michael@0 180 value: record.value
michael@0 181 };
michael@0 182 this._processChange(change);
michael@0 183 },
michael@0 184
michael@0 185 remove: function (record) {
michael@0 186 this._log.trace("Removing form record: " + record.id);
michael@0 187 let change = {
michael@0 188 op: "remove",
michael@0 189 guid: record.id
michael@0 190 };
michael@0 191 this._processChange(change);
michael@0 192 },
michael@0 193
michael@0 194 update: function (record) {
michael@0 195 this._log.trace("Ignoring form record update request!");
michael@0 196 },
michael@0 197
michael@0 198 wipe: function () {
michael@0 199 let change = {
michael@0 200 op: "remove"
michael@0 201 };
michael@0 202 FormWrapper._updateSpinningly(change);
michael@0 203 }
michael@0 204 };
michael@0 205
michael@0 206 function FormTracker(name, engine) {
michael@0 207 Tracker.call(this, name, engine);
michael@0 208 }
michael@0 209 FormTracker.prototype = {
michael@0 210 __proto__: Tracker.prototype,
michael@0 211
michael@0 212 QueryInterface: XPCOMUtils.generateQI([
michael@0 213 Ci.nsIObserver,
michael@0 214 Ci.nsISupportsWeakReference]),
michael@0 215
michael@0 216 startTracking: function() {
michael@0 217 Svc.Obs.add("satchel-storage-changed", this);
michael@0 218 },
michael@0 219
michael@0 220 stopTracking: function() {
michael@0 221 Svc.Obs.remove("satchel-storage-changed", this);
michael@0 222 },
michael@0 223
michael@0 224 observe: function (subject, topic, data) {
michael@0 225 Tracker.prototype.observe.call(this, subject, topic, data);
michael@0 226
michael@0 227 switch (topic) {
michael@0 228 case "satchel-storage-changed":
michael@0 229 if (data == "formhistory-add" || data == "formhistory-remove") {
michael@0 230 let guid = subject.QueryInterface(Ci.nsISupportsString).toString();
michael@0 231 this.trackEntry(guid);
michael@0 232 }
michael@0 233 break;
michael@0 234 }
michael@0 235 },
michael@0 236
michael@0 237 trackEntry: function (guid) {
michael@0 238 this.addChangedID(guid);
michael@0 239 this.score += SCORE_INCREMENT_MEDIUM;
michael@0 240 },
michael@0 241 };

mercurial