Fri, 16 Jan 2015 18:13:44 +0100
Integrate suggestion from review to improve consistency with existing code.
1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 /**
6 * This class helps us batch a series of async calls to the db.
7 * If any of the tokens is in the database, we fire callback with
8 * true as a param. If all the tokens are not in the database,
9 * we fire callback with false as a param.
10 * This is an "Abstract" base class. Subclasses need to supply
11 * the condition_ method.
12 *
13 * @param tokens Array of strings to lookup in the db
14 * @param tableName String name of the table
15 * @param callback Function callback function that takes true if the condition
16 * passes.
17 */
18 function MultiQuerier(tokens, tableName, callback) {
19 this.tokens_ = tokens;
20 this.tableName_ = tableName;
21 this.callback_ = callback;
22 this.dbservice_ = Cc["@mozilla.org/url-classifier/dbservice;1"]
23 .getService(Ci.nsIUrlClassifierDBService);
24 // We put the current token in this variable.
25 this.key_ = null;
26 }
28 /**
29 * Run the remaining tokens against the db.
30 */
31 MultiQuerier.prototype.run = function() {
32 if (this.tokens_.length == 0) {
33 this.callback_.handleEvent(false);
34 this.dbservice_ = null;
35 this.callback_ = null;
36 return;
37 }
39 this.key_ = this.tokens_.pop();
40 G_Debug(this, "Looking up " + this.key_ + " in " + this.tableName_);
41 this.dbservice_.exists(this.tableName_, this.key_,
42 BindToObject(this.result_, this));
43 }
45 /**
46 * Callback from the db. If the returned value passes the this.condition_
47 * test, go ahead and call the main callback.
48 */
49 MultiQuerier.prototype.result_ = function(value) {
50 if (this.condition_(value)) {
51 this.callback_.handleEvent(true)
52 this.dbservice_ = null;
53 this.callback_ = null;
54 } else {
55 this.run();
56 }
57 }
59 // Subclasses must override this.
60 MultiQuerier.prototype.condition_ = function(value) {
61 throw "MultiQuerier is an abstract base class";
62 }
65 /**
66 * Concrete MultiQuerier that stops if the key exists in the db.
67 */
68 function ExistsMultiQuerier(tokens, tableName, callback) {
69 MultiQuerier.call(this, tokens, tableName, callback);
70 this.debugZone = "existsMultiQuerier";
71 }
72 ExistsMultiQuerier.inherits(MultiQuerier);
74 ExistsMultiQuerier.prototype.condition_ = function(value) {
75 return value.length > 0;
76 }
79 /**
80 * Concrete MultiQuerier that looks up a key, decrypts it, then
81 * checks the the resulting regular expressions for a match.
82 * @param tokens Array of hosts
83 */
84 function EnchashMultiQuerier(tokens, tableName, callback, url) {
85 MultiQuerier.call(this, tokens, tableName, callback);
86 this.url_ = url;
87 this.enchashDecrypter_ = new PROT_EnchashDecrypter();
88 this.debugZone = "enchashMultiQuerier";
89 }
90 EnchashMultiQuerier.inherits(MultiQuerier);
92 EnchashMultiQuerier.prototype.run = function() {
93 if (this.tokens_.length == 0) {
94 this.callback_.handleEvent(false);
95 this.dbservice_ = null;
96 this.callback_ = null;
97 return;
98 }
99 var host = this.tokens_.pop();
100 this.key_ = host;
101 var lookupKey = this.enchashDecrypter_.getLookupKey(host);
102 this.dbservice_.exists(this.tableName_, lookupKey,
103 BindToObject(this.result_, this));
104 }
106 EnchashMultiQuerier.prototype.condition_ = function(encryptedValue) {
107 if (encryptedValue.length > 0) {
108 // We have encrypted regular expressions for this host. Let's
109 // decrypt them and see if we have a match.
110 var decrypted = this.enchashDecrypter_.decryptData(encryptedValue,
111 this.key_);
112 var res = this.enchashDecrypter_.parseRegExps(decrypted);
113 for (var j = 0; j < res.length; j++) {
114 if (res[j].test(this.url_)) {
115 return true;
116 }
117 }
118 }
119 return false;
120 }