summaryrefslogtreecommitdiffstats
path: root/services/sync/tps/extensions/tps/resource/modules/forms.sys.mjs
blob: 35b5f5c03b0329e7f398f799f3b53f913d5b162b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/* This is a JavaScript module (JSM) to be imported via
   ChromeUtils.import() and acts as a singleton. Only the following
   listed symbols will exposed on import, and only when and where imported.
  */

import { Logger } from "resource://tps/logger.sys.mjs";

import { FormHistory } from "resource://gre/modules/FormHistory.sys.mjs";

/**
 * FormDB
 *
 * Helper object containing methods to interact with the FormHistory module.
 */
var FormDB = {
  async _update(data) {
    await FormHistory.update(data);
  },

  /**
   * insertValue
   *
   * Adds the specified value for the specified fieldname into form history.
   *
   * @param fieldname The form fieldname to insert
   * @param value The form value to insert
   * @param us The time, in microseconds, to use for the lastUsed
   *        and firstUsed columns
   * @return Promise<undefined>
   */
  insertValue(fieldname, value, us) {
    let data = {
      op: "add",
      fieldname,
      value,
      timesUsed: 1,
      firstUsed: us,
      lastUsed: us,
    };
    return this._update(data);
  },

  /**
   * updateValue
   *
   * Updates a row in the moz_formhistory table with a new value.
   *
   * @param id The id of the row to update
   * @param newvalue The new value to set
   * @return Promise<undefined>
   */
  updateValue(id, newvalue) {
    return this._update({ op: "update", guid: id, value: newvalue });
  },

  /**
   * getDataForValue
   *
   * Retrieves a set of values for a row in the database that
   * corresponds to the given fieldname and value.
   *
   * @param fieldname The fieldname of the row to query
   * @param value The value of the row to query
   * @return Promise<null if no row is found with the specified fieldname and value,
   *         or an object containing the row's guid, lastUsed, and firstUsed
   *         values>
   */
  async getDataForValue(fieldname, value) {
    let results = await FormHistory.search(["guid", "lastUsed", "firstUsed"], {
      fieldname,
      value,
    });
    if (results.length > 1) {
      throw new Error("more than 1 result for this query");
    }
    return results;
  },

  /**
   * remove
   *
   * Removes the specified GUID from the database.
   *
   * @param guid The guid of the item to delete
   * @return Promise<>
   */
  remove(guid) {
    return this._update({ op: "remove", guid });
  },
};

/**
 * FormData class constructor
 *
 * Initializes instance properties.
 */
export function FormData(props, msSinceEpoch) {
  this.fieldname = null;
  this.value = null;
  this.date = 0;
  this.newvalue = null;
  this.usSinceEpoch = msSinceEpoch * 1000;

  for (var prop in props) {
    if (prop in this) {
      this[prop] = props[prop];
    }
  }
}

/**
 * FormData instance methods
 */
FormData.prototype = {
  /**
   * hours_to_us
   *
   * Converts hours since present to microseconds since epoch.
   *
   * @param hours The number of hours since the present time (e.g., 0 is
   *        'now', and -1 is 1 hour ago)
   * @return the corresponding number of microseconds since the epoch
   */
  hours_to_us(hours) {
    return this.usSinceEpoch + hours * 60 * 60 * 1000 * 1000;
  },

  /**
   * Create
   *
   * If this FormData object doesn't exist in the moz_formhistory database,
   * add it.  Throws on error.
   *
   * @return nothing
   */
  Create() {
    Logger.AssertTrue(
      this.fieldname != null && this.value != null,
      "Must specify both fieldname and value"
    );

    return FormDB.getDataForValue(this.fieldname, this.value).then(formdata => {
      if (!formdata) {
        // this item doesn't exist yet in the db, so we need to insert it
        return FormDB.insertValue(
          this.fieldname,
          this.value,
          this.hours_to_us(this.date)
        );
      }
      /* Right now, we ignore this case.  If bug 552531 is ever fixed,
         we might need to add code here to update the firstUsed or
         lastUsed fields, as appropriate.
       */
      return null;
    });
  },

  /**
   * Find
   *
   * Attempts to locate an entry in the moz_formhistory database that
   * matches the fieldname and value for this FormData object.
   *
   * @return true if this entry exists in the database, otherwise false
   */
  Find() {
    return FormDB.getDataForValue(this.fieldname, this.value).then(formdata => {
      let status = formdata != null;
      if (status) {
        /*
        //form history dates currently not synced!  bug 552531
        let us = this.hours_to_us(this.date);
        status = Logger.AssertTrue(
          us >= formdata.firstUsed && us <= formdata.lastUsed,
          "No match for with that date value");

        if (status)
        */
        this.id = formdata.guid;
      }
      return status;
    });
  },

  /**
   * Remove
   *
   * Removes the row represented by this FormData instance from the
   * moz_formhistory database.
   *
   * @return nothing
   */
  async Remove() {
    const formdata = await FormDB.getDataForValue(this.fieldname, this.value);
    if (!formdata) {
      return;
    }
    await FormDB.remove(formdata.guid);
  },
};