diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul
index a5ddb078e44b..2377f0a4dc22 100644
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -267,7 +267,7 @@
#ifdef MOZ_SAFE_BROWSING
-
diff --git a/browser/components/safebrowsing/content/list-warden.js b/browser/components/safebrowsing/content/list-warden.js
index 453c7f1ece47..39612b2e5c30 100644
--- a/browser/components/safebrowsing/content/list-warden.js
+++ b/browser/components/safebrowsing/content/list-warden.js
@@ -131,109 +131,104 @@ PROT_ListWarden.prototype.registerWhiteTable = function(tableName) {
return result;
}
-/**
- * Internal method that looks up a url in a set of tables
- *
- * @param tables array of table names
- * @param url URL to look up
- * @returns Boolean indicating if the url is in one of the tables
- */
-PROT_ListWarden.prototype.isURLInTables_ = function(tables, url) {
- for (var i = 0; i < tables.length; ++i) {
- if (this.listManager_.safeExists(tables[i], url))
- return true;
- }
- return false;
-}
-
-/**
- * Internal method that looks up a url in the white list.
- *
- * @param url URL to look up
- * @returns Boolean indicating if the url is on our whitelist
- */
-PROT_ListWarden.prototype.isWhiteURL_ = function(url) {
- if (!this.listManager_)
- return false;
-
- var whitelisted = this.isURLInTables_(this.whiteTables_, url);
-
- if (whitelisted)
- G_Debug(this, "Whitelist hit: " + url);
-
- return whitelisted;
-}
-
-/**
- * External method that looks up a url on the whitelist, used by the
- * content-analyzer.
- *
- * @param url The URL to check
- * @returns Boolean indicating if the url is on the whitelist
- */
-PROT_ListWarden.prototype.isWhiteURL = function(url) {
- return this.isWhiteURL_(url);
-}
-
-/**
- * Internal method that looks up a url in the black lists. Skips the lookup if
- * the URL is on our whitelist(s).
- *
- * @param url URL to look up
- * @returns Boolean indicating if the url is on our blacklist(s)
- */
-PROT_ListWarden.prototype.isBlackURL_ = function(url) {
- if (!this.listManager_)
- return false;
-
- var blacklisted = this.isURLInTables_(this.blackTables_, url);
-
- if (blacklisted)
- G_Debug(this, "Blacklist hit: " + url);
-
- return blacklisted;
-}
-
/**
* Internal method that looks up a url in both the white and black lists.
*
* If there is conflict, the white list has precedence over the black list.
*
+ * This is tricky because all database queries are asynchronous. So we need
+ * to chain together our checks against white and black tables. We use
+ * MultiTableQuerier (see below) to manage this.
+ *
* @param url URL to look up
- * @returns Boolean indicating if the url is phishy.
+ * @param evilCallback Function if the url is evil, we call this function.
*/
-PROT_ListWarden.prototype.isEvilURL_ = function(url) {
- return !this.isWhiteURL_(url) && this.isBlackURL_(url);
+PROT_ListWarden.prototype.isEvilURL_ = function(url, evilCallback) {
+ (new MultiTableQuerier(url,
+ this.whiteTables_,
+ this.blackTables_,
+ evilCallback)).run();
}
-// Some unittests
-// TODO something more appropriate
+/**
+ * This class helps us query multiple tables even though each table check
+ * is asynchronous. It provides callbacks for each listManager lookup
+ * and decides whether we need to continue querying or not. After
+ * instantiating the method, use run() to invoke.
+ *
+ * @param url String The url to check
+ * @param whiteTables Array of strings with each white table name
+ * @param blackTables Array of strings with each black table name
+ * @param evilCallback Function to call if it is an evil url
+ */
+function MultiTableQuerier(url, whiteTables, blackTables, evilCallback) {
+ this.debugZone = "multitablequerier";
+ this.url_ = url;
-function TEST_PROT_ListWarden() {
- if (G_GDEBUG) {
- var z = "listwarden UNITTEST";
- G_debugService.enableZone(z);
- G_Debug(z, "Starting");
+ // Since we pop from whiteTables_ and blackTables_, we need to make a copy.
+ this.whiteTables_ = [];
+ this.blackTables_ = [];
+ for (var i = 0; i < whiteTables.length; ++i) {
+ this.whiteTables_.push(whiteTables[i]);
+ }
+ for (var i = 0; i < blackTables.length; ++i) {
+ this.blackTables_.push(blackTables[i]);
+ }
- var threadQueue = new TH_ThreadQueue();
- var listManager = new PROT_ListManager(threadQueue, true /* testing */);
-
- var warden = new PROT_ListWarden(listManager);
+ this.evilCallback_ = evilCallback;
+ this.listManager_ = Cc["@mozilla.org/url-classifier/listmanager;1"]
+ .getService(Ci.nsIUrlListManager);
+}
- // Just some really simple test
- G_Assert(z, warden.registerWhiteTable("test-white-domain"),
- "Failed to register test-white-domain table");
- G_Assert(z, warden.registerWhiteTable("test-black-url"),
- "Failed to register test-black-url table");
- listManager.safeInsert("test-white-domain", "http://foo.com/good", "1");
- listManager.safeInsert("test-black-url", "http://foo.com/good/1", "1");
- listManager.safeInsert("test-black-url", "http://foo.com/bad/1", "1");
-
- G_Assert(z, !warden.isEvilURL_("http://foo.com/good/1"),
- "White listing is not working.");
- G_Assert(z, warden.isEvilURL_("http://foo.com/bad/1"),
- "Black listing is not working.");
-
- G_Debug(z, "PASSED");
+/**
+ * We first query the white tables in succession. If any contain
+ * the url, we stop. If none contain the url, we query the black tables
+ * in succession. If any contain the url, we call evilCallback and
+ * stop. If none of the black tables contain the url, then we just stop
+ * (i.e., it's not black url).
+ */
+MultiTableQuerier.prototype.run = function() {
+ if (this.whiteTables_.length > 0) {
+ var tableName = this.whiteTables_.pop();
+ G_Debug(this, "Looking in whitetable: " + tableName);
+ this.listManager_.safeExists(tableName, this.url_,
+ BindToObject(this.whiteTableCallback_,
+ this));
+ } else if (this.blackTables_.length > 0) {
+ var tableName = this.blackTables_.pop();
+ G_Debug(this, "Looking in blacktable: " + tableName);
+ this.listManager_.safeExists(tableName, this.url_,
+ BindToObject(this.blackTableCallback_,
+ this));
+ } else {
+ // No tables left to check, so we quit.
+ G_Debug(this, "Not found in any tables: " + this.url_);
+ }
+}
+
+/**
+ * After checking a white table, we return here. If the url is found,
+ * we can stop. Otherwise, we call run again.
+ */
+MultiTableQuerier.prototype.whiteTableCallback_ = function(isFound) {
+ G_Debug(this, "whiteTableCallback_: " + isFound);
+ if (!isFound)
+ this.run();
+ else
+ G_Debug(this, "Found in whitelist: " + this.url_)
+}
+
+/**
+ * After checking a black table, we return here. If the url is found,
+ * we can call the evilCallback and stop. Otherwise, we call run again.
+ */
+MultiTableQuerier.prototype.blackTableCallback_ = function(isFound) {
+ G_Debug(this, "blackTableCallback_: " + isFound);
+ if (!isFound) {
+ this.run();
+ } else {
+ // In the blacklist, must be an evil url.
+ G_Debug(this, "Found in blacklist: " + this.url_)
+ this.evilCallback_();
}
}
diff --git a/browser/components/safebrowsing/content/phishing-warden.js b/browser/components/safebrowsing/content/phishing-warden.js
index aac59387d552..caa65f194141 100644
--- a/browser/components/safebrowsing/content/phishing-warden.js
+++ b/browser/components/safebrowsing/content/phishing-warden.js
@@ -266,20 +266,15 @@ PROT_PhishingWarden.prototype.onDocNavStart = function(e) {
// We're enabled. Either send a request off or check locally
// TODO: move this logic to checkUrl, formalize the error callback
if (this.checkRemote_) {
- // Use local whitelists to suppress remote BL lookups.
- if (!this.isWhiteURL_(url)) {
- G_Debug(this, "Local whitelist lookup failed");
- this.fetcher_.get(url,
- BindToObject(this.onTRFetchComplete,
- this,
- request));
- } else {
- G_Debug(this, "WL suppressing BL lookup for " + url);
- }
+ // TODO: Use local whitelists to suppress remote BL lookups.
+ this.fetcher_.get(url,
+ BindToObject(this.onTRFetchComplete,
+ this,
+ request));
} else {
- if (this.checkUrl(url)) {
- this.houstonWeHaveAProblem_(request);
- }
+ this.checkUrl(url, BindToObject(this.houstonWeHaveAProblem_,
+ this,
+ request));
}
}
}
@@ -432,22 +427,26 @@ PROT_PhishingWarden.prototype.isBlacklistTestURL = function(url) {
/**
* Look the URL up in our local blacklists
*
+ * @param url URL to check
* @param callback Function to invoke if there is a problem.
*
- * @param url URL to check
*/
-PROT_PhishingWarden.prototype.checkUrl = function(url) {
+PROT_PhishingWarden.prototype.checkUrl = function(url, callback) {
G_Debug(this, "Checking URL for " + url);
-
- if (this.isEvilURL_(url) || this.isBlacklistTestURL(url)) {
- G_Debug(this, "Local blacklist hit");
- // maybe send a report
- (new PROT_Reporter).report("phishblhit", url);
- return true;
+ if (this.isBlacklistTestURL(url)) {
+ callback();
+ } else {
+ // We wrap the callback because we also want
+ // to report the blacklist hit to our data provider.
+ function evilCallback() {
+ G_Debug("evilCallback", "Local blacklist hit");
+ // maybe send a report
+ (new PROT_Reporter).report("phishblhit", url);
+ callback();
+ }
+ // Check the local lists.
+ this.isEvilURL_(url, evilCallback);
}
-
- G_Debug(this, "Local blacklist miss");
- return false;
}
/**
diff --git a/browser/components/safebrowsing/src/safebrowsingApplication.js b/browser/components/safebrowsing/src/safebrowsingApplication.js
index e3476b6ea6cf..ccd3064865f5 100644
--- a/browser/components/safebrowsing/src/safebrowsingApplication.js
+++ b/browser/components/safebrowsing/src/safebrowsingApplication.js
@@ -1,6 +1,6 @@
const Cc = Components.classes;
const Ci = Components.interfaces;
-const G_GDEBUG = true;
+const G_GDEBUG = false;
// Use subscript loader to load files. The files in ../content get mapped
// to chrome://browser/content/safebrowsing/. Order matters if one file depends
diff --git a/toolkit/components/url-classifier/content/list-warden.js b/toolkit/components/url-classifier/content/list-warden.js
deleted file mode 100644
index 2be5e4d50d64..000000000000
--- a/toolkit/components/url-classifier/content/list-warden.js
+++ /dev/null
@@ -1,225 +0,0 @@
-/* ***** 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 Google Safe Browsing.
- *
- * The Initial Developer of the Original Code is Google Inc.
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Niels Provos (original author)d
-
- * Fritz Schneider
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either 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 ***** */
-
-// A warden that knows how to register lists with a listmanager and keep them
-// updated if necessary. The ListWarden also provides a simple interface to
-// check if a URL is evil or not. Specialized wardens like the PhishingWarden
-// inherit from it.
-//
-// Classes that inherit from ListWarden are responsible for calling
-// enableTableUpdates or disableTableUpdates. This usually entails
-// registering prefObservers and calling enable or disable in the base
-// class as appropriate.
-//
-
-/**
- * Abtracts the checking of user/browser actions for signs of
- * phishing.
- *
- * @param ListManager ListManager that allows us to check against white
- * and black lists.
- *
- * @constructor
- */
-function PROT_ListWarden(listManager) {
- this.debugZone = "listwarden";
- this.listManager_ = listManager;
-
- // Use this to query preferences
- this.prefs_ = new G_Preferences();
-
- // Once we register tables, their respective names will be listed here.
- this.blackTables_ = [];
- this.whiteTables_ = [];
- this.sandboxUpdates_ = [];
-}
-
-/**
- * Tell the ListManger to keep all of our tables updated
- */
-
-PROT_ListWarden.prototype.enableTableUpdates = function() {
- this.listManager_.enableUpdateTables(this.blackTables_);
- this.listManager_.enableUpdateTables(this.whiteTables_);
-}
-
-/**
- * Tell the ListManager to stop updating our tables
- */
-
-PROT_ListWarden.prototype.disableTableUpdates = function() {
- this.listManager_.disableUpdateTables(this.blackTables_);
- this.listManager_.disableUpdateTables(this.whiteTables_);
-}
-
-/**
- * Tell the ListManager to keep sandbox updated. Don't tie this to the wl/bl
- * updates.
- */
-PROT_ListWarden.prototype.enableSandboxUpdates = function() {
- this.listManager_.enableUpdateTables(this.sandboxUpdates_);
-}
-
-/**
- * Tell the ListManager not to keep sandbox updated. Don't tie this to the
- * wl/bl updates.
- */
-PROT_ListWarden.prototype.disableSandboxUpdates = function() {
- this.listManager_.disableUpdateTables(this.sandboxUpdates_);
-}
-
-/**
- * Register a new black list table with the list manager
- * @param tableName - name of the table to register
- * @returns true if the table could be registered, false otherwise
- */
-
-PROT_ListWarden.prototype.registerBlackTable = function(tableName) {
- var result = this.listManager_.registerTable(tableName);
- if (result)
- this.blackTables_.push(tableName);
- return result;
-}
-
-/**
- * Register a new white list table with the list manager
- * @param tableName - name of the table to register
- * @returns true if the table could be registered, false otherwise
- */
-
-PROT_ListWarden.prototype.registerWhiteTable = function(tableName) {
- var result = this.listManager_.registerTable(tableName);
- if (result)
- this.whiteTables_.push(tableName);
- return result;
-}
-
-/**
- * Internal method that looks up a url in a set of tables
- *
- * @param tables array of table names
- * @param url URL to look up
- * @returns Boolean indicating if the url is in one of the tables
- */
-PROT_ListWarden.prototype.isURLInTables_ = function(tables, url) {
- for (var i = 0; i < tables.length; ++i) {
- if (this.listManager_.safeLookup(tables[i], url))
- return true;
- }
- return false;
-}
-
-/**
- * Internal method that looks up a url in the white list.
- *
- * @param url URL to look up
- * @returns Boolean indicating if the url is on our whitelist
- */
-PROT_ListWarden.prototype.isWhiteURL_ = function(url) {
- if (!this.listManager_)
- return false;
-
- var whitelisted = this.isURLInTables_(this.whiteTables_, url);
-
- if (whitelisted)
- G_Debug(this, "Whitelist hit: " + url);
-
- return whitelisted;
-}
-
-/**
- * Internal method that looks up a url in the black lists.
- *
- * @param url URL to look up
- * @returns Boolean indicating if the url is on our blacklist(s)
- */
-PROT_ListWarden.prototype.isBlackURL_ = function(url) {
- if (!this.listManager_)
- return false;
-
- var blacklisted = this.isURLInTables_(this.blackTables_, url);
-
- if (blacklisted)
- G_Debug(this, "Blacklist hit: " + url);
-
- return blacklisted;
-}
-
-/**
- * Internal method that looks up a url in both the white and black lists.
- *
- * If there is conflict, the white list has precedence over the black list.
- *
- * @param url URL to look up
- * @returns Boolean indicating if the url is phishy.
- */
-PROT_ListWarden.prototype.isEvilURL_ = function(url) {
- return !this.isWhiteURL_(url) && this.isBlackURL_(url);
-}
-
-// Some unittests
-// TODO something more appropriate
-
-function TEST_PROT_ListWarden() {
- if (G_GDEBUG) {
- var z = "listwarden UNITTEST";
- G_debugService.enableZone(z);
- G_Debug(z, "Starting");
-
- var threadQueue = new TH_ThreadQueue();
- var listManager = new PROT_ListManager(threadQueue, true /* testing */);
-
- var warden = new PROT_ListWarden(listManager);
-
- // Just some really simple test
- G_Assert(z, warden.registerWhiteTable("test-white-domain"),
- "Failed to register test-white-domain table");
- G_Assert(z, warden.registerWhiteTable("test-black-url"),
- "Failed to register test-black-url table");
- listManager.safeInsert("test-white-domain", "http://foo.com/good", "1");
- listManager.safeInsert("test-black-url", "http://foo.com/good/1", "1");
- listManager.safeInsert("test-black-url", "http://foo.com/bad/1", "1");
-
- G_Assert(z, !warden.isEvilURL_("http://foo.com/good/1"),
- "White listing is not working.");
- G_Assert(z, warden.isEvilURL_("http://foo.com/bad/1"),
- "Black listing is not working.");
-
- G_Debug(z, "PASSED");
- }
-}
diff --git a/toolkit/components/url-classifier/content/listmanager.js b/toolkit/components/url-classifier/content/listmanager.js
index 4368b706f4af..68965a2b320c 100644
--- a/toolkit/components/url-classifier/content/listmanager.js
+++ b/toolkit/components/url-classifier/content/listmanager.js
@@ -268,65 +268,21 @@ PROT_ListManager.prototype.stopUpdateChecker = function() {
* use this because at certain points our tables might not be loaded,
* and querying them could throw.
*
- * @param table Name of the table that we want to consult
- * @param key Key for table lookup
- * @returns false or the value in the table corresponding to key.
- * If the table name does not exist, we return false, too.
+ * @param table String Name of the table that we want to consult
+ * @param key String Key for table lookup
+ * @param callback nsIUrlListManagerCallback (ie., Function) given false or the
+ * value in the table corresponding to key. If the table name does not
+ * exist, we return false, too.
*/
-PROT_ListManager.prototype.safeExists = function(table, key) {
- var result = false;
+PROT_ListManager.prototype.safeExists = function(table, key, callback) {
try {
+ G_Debug(this, "safeExists: " + table + ", " + key);
var map = this.tablesData[table];
- result = map.exists(key);
+ map.exists(key, callback);
} catch(e) {
- result = false;
G_Debug(this, "safeExists masked failure for " + table + ", key " + key + ": " + e);
+ callback.handleEvent(false);
}
-
- return result;
-}
-
-/**
- * Provides an exception free way to insert data into a table.
- * @param table Name of the table that we want to consult
- * @param key Key for table insert
- * @param value Value for table insert
- * @returns true if the value could be inserted, false otherwise
- */
-PROT_ListManager.prototype.safeInsert = function(table, key, value) {
- if (!this.tablesKnown_[table]) {
- G_Debug(this, "Unknown table: " + table);
- return false;
- }
- if (!this.tablesData[table])
- this.tablesData[table] = newUrlClassifierTable(table);
- try {
- this.tablesData[table].insert(key, value);
- } catch (e) {
- G_Debug(this, "Cannot insert key " + key + " value " + value);
- G_Debug(this, e);
- return false;
- }
-
- return true;
-}
-
-/**
- * Provides an exception free way to remove data from a table.
- * @param table Name of the table that we want to consult
- * @param key Key for table erase
- * @returns true if the value could be removed, false otherwise
- */
-PROT_ListManager.prototype.safeRemove = function(table, key) {
- if (!this.tablesKnown_[table]) {
- G_Debug(this, "Unknown table: " + table);
- return false;
- }
-
- if (!this.tablesData[table])
- return false;
-
- return this.tablesData[table].remove(key);
}
/**
@@ -348,43 +304,30 @@ PROT_ListManager.prototype.loadTableVersions_ = function() {
}
/**
- * Get lines of the form "[goog-black-enchash 1.1234]" or
- * "[goog-white-url 1.1234 update]" and set the version numbers in the user
- * pref.
- * @param updateString String containing the response from the server.
- * @return Array a list of table names
+ * Callback from db update service. As new tables are added to the db,
+ * this callback is fired so we can update the version number.
+ * @param versionString String containing the table update response from the
+ * server
*/
-PROT_ListManager.prototype.setTableVersions_ = function(updateString) {
- var updatedTables = [];
+PROT_ListManager.prototype.setTableVersion_ = function(versionString) {
+ G_Debug(this, "Got version string: " + versionString);
+ var versionParser = new PROT_VersionParser("");
+ if (versionParser.fromString(versionString)) {
+ var tableName = versionParser.type;
+ var versionNumber = versionParser.versionString();
+ var prefBase = kTableVersionPrefPrefix;
- var prefBase = kTableVersionPrefPrefix;
- var startPos = updateString.indexOf('[');
- var endPos;
- while (startPos != -1) {
- // [ needs to be the start of a new line
- if (0 == startPos || ('\n' == updateString[startPos - 1] &&
- '\n' == updateString[startPos - 2])) {
- endPos = updateString.indexOf('\n', startPos);
- if (endPos != -1) {
- var line = updateString.substring(startPos, endPos);
- var versionParser = new PROT_VersionParser("dummy");
-
- if (versionParser.fromString(line)) {
- var tableName = versionParser.type;
- var version = versionParser.major + '.' + versionParser.minor;
- G_Debug(this, "Set table version for " + tableName + ": " + version);
- this.prefs_.setPref(prefBase + tableName, version);
- this.tablesKnown_[tableName].ImportVersion(versionParser);
-
- updatedTables.push(tableName);
- }
- }
+ this.prefs_.setPref(prefBase + tableName, versionNumber);
+
+ if (!this.tablesKnown_[tableName]) {
+ this.tablesKnown_[tableName] = versionParser;
+ } else {
+ this.tablesKnown_[tableName].ImportVersion(versionParser);
}
- // This could catch option params, but that's ok. The double newline
- // check will skip over it.
- startPos = updateString.indexOf('[', startPos + 1);
+
+ if (!this.tablesData[tableName])
+ this.tablesData[tableName] = newUrlClassifierTable(tableName);
}
- return updatedTables;
}
/**
@@ -485,32 +428,12 @@ PROT_ListManager.prototype.rpcDone = function(data) {
return;
}
- // List updates (local lists) don't work yet. See bug 336203.
- throw Exception("dbservice not yet implemented.");
-
var dbUpdateSrv = Cc["@mozilla.org/url-classifier/dbservice;1"]
.getService(Ci.nsIUrlClassifierDBService);
- // Update the tables on disk.
- try {
- dbUpdateSrv.updateTables(data);
- } catch (e) {
- // dbUpdateSrv will throw an error if the background thread is already
- // working. In this case, we just wait for the next scheduled update.
- G_Debug(this, "Skipping update, write thread busy.");
- return;
- }
-
- // While the update is being processed by a background thread, we need
- // to also update the table versions.
- var tableNames = this.setTableVersions_(data);
- G_Debug(this, "Updated tables: " + tableNames);
-
- for (var t = 0, name = null; name = tableNames[t]; ++t) {
- // Create the table object if it doesn't exist.
- if (!this.tablesData[name])
- this.tablesData[name] = newUrlClassifierTable(name);
- }
+ // Update the tables on disk in a background thread. Multiple updates
+ // will be queue up.
+ dbUpdateSrv.updateTables(data, BindToObject(this.setTableVersion_, this));
}
/**
diff --git a/toolkit/components/url-classifier/content/map.js b/toolkit/components/url-classifier/content/map.js
deleted file mode 100644
index d554f110ec89..000000000000
--- a/toolkit/components/url-classifier/content/map.js
+++ /dev/null
@@ -1,232 +0,0 @@
-/* ***** 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 Google Safe Browsing.
- *
- * The Initial Developer of the Original Code is Google Inc.
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Fritz Schneider (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either 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 ***** */
-
-
-// This is a map over which you can iterate (you can't get an iterator
-// for an Object used as a map). It is important to have an iterable
-// map if you have a large numbe ofkeys and you wish to process them
-// in chunks, for example on a thread.
-//
-// This Map's operations are all O(1) plus the time of the native
-// operations on its arrays and object. The tradeoff for this speed is
-// that the size of the map is always non-decreasing. That is, when an
-// item is remove()'d, it is merely marked as invalid and not actually
-// removed.
-//
-// This map is not safe if your keys are objects (they'll get
-// stringified to the same value in non-debug builds).
-//
-// Interface:
-// insert(key, value)
-// remove(key)
-// exists(key)
-// getList() // This is our poor man's iterator
-// forEach(someFunc)
-// replace(otherMap) // Clones otherMap, replacing the current map
-// count // readonly attribute
-//
-// TODO: we could easily have this map periodically compact itself so as
-// to eliminate the size tradeoff.
-
-/**
- * Create a new Map
- *
- * @constructor
- * @param opt_name A string used to name the map
- */
-function G_Map(opt_name) {
- this.debugZone = "map";
- this.name = "noname";
-
- // We store key/value pairs sequentially in membersArray
- this.membersArray_ = [];
-
- // In membersMap we map from keys to indices in the membersArray
- this.membersMap_ = {};
- this.count_ = 0;
-
- // set to true to allow list manager to update
- this.needsUpdate = false;
-}
-
-/**
- * Add an item
- *
- * @param key An key to add (overwrites previous key)
- * @param value The value to store at that key
- */
-G_Map.prototype.insert = function(key, value) {
- if (key == null)
- throw new Error("Can't use null as a key");
- else if (typeof key == "object")
- throw new Error("This class is not objectsafe; use ObjectSafeMap");
- if (value === undefined)
- throw new Error("Can't store undefined values in this map");
-
- // Get rid of the old value, if there was one, and increment count if not
- var oldIndexInArray = this.membersMap_[key];
- if (typeof oldIndexInArray == "number")
- this.membersArray_[oldIndexInArray] = undefined;
- else
- this.count_++;
-
- var indexInArray = this.membersArray_.length;
- this.membersArray_.push({ "key": key, "value": value});
- this.membersMap_[key] = indexInArray;
-}
-
-/**
- * Remove a key from the map
- *
- * @param key The key to remove
- * @returns Boolean indicating if the key was removed
- */
-G_Map.prototype.remove = function(key) {
- var indexInArray = this.membersMap_[key];
-
- if (indexInArray === undefined)
- return false;
-
- this.count_--;
- delete this.membersMap_[key];
- // We could slice here, but that could be expensive if the map large
- this.membersArray_[indexInArray] = undefined;
-
- return true;
-}
-
-/**
- * Private lookup function
- *
- * @param key The key to look up
- * @returns The value at that key or undefined if it doesn't exist
- */
-G_Map.prototype.find_ = function(key) {
- var indexInArray = this.membersMap_[key];
- return ((indexInArray === undefined) ?
- undefined :
- this.membersArray_[indexInArray].value);
-}
-
-/**
- * Public lookup function
- *
- * @param key The key to look up
- * @returns The value at that key or undefined if it doesn't exist
- */
-G_Map.prototype.exists = function(key) {
- return this.find_(key);
-}
-
-/**
- * Return the list of the keys we have. Use findValue to get the associated
- * value.
- *
- * TODO: its probably better to expose a real iterator, but this works
- * TODO: getting keys and values is a pain, do something more clever
- *
- * @returns Array of items in the map, some entries of which might be
- * undefined. Each item is an object with members key and
- * value
- */
-G_Map.prototype.getKeys = function(count) {
- var ret = [];
- for (var i = 0; i < this.membersArray_.length; ++i) {
- ret.push(this.membersArray_[i].key);
- }
- count.value = ret.length;
- return ret;
-}
-
-G_Map.prototype.findValue = function(key) {
- return this.find_(key);
-}
-
-/**
- * Replace one map with the content of another
- *
- * IMPORTANT NOTE: This method copies references to objects, it does
- * NOT copy the objects themselves.
- *
- * @param other Reference to a G_Map that we should clone
- */
-G_Map.prototype.replace = function(other) {
- this.membersMap_ = {};
- this.membersArray_ = [];
-
- // TODO Make this faster, and possibly run it on a thread
- var lst = {};
- var otherList = other.getList(lst);
- for (var i = 0; i < otherList.length; i++)
- if (otherList[i]) {
- var index = this.membersArray_.length;
- this.membersArray_.push(otherList[i]);
- this.membersMap_[otherList[i].key] = index;
- }
- this.count_ = other.count;
-}
-
-/**
- * Apply a function to each of the key value pairs.
- *
- * @param func Function to apply to the map's key value pairs
- */
-G_Map.prototype.forEach = function(func) {
- if (typeof func != "function")
- throw new Error("argument to forEach is not a function, it's a(n) " +
- typeof func);
-
- for (var i = 0; i < this.membersArray_.length; i++)
- if (this.membersArray_[i])
- func(this.membersArray_[i].key, this.membersArray_[i].value);
-}
-
-G_Map.prototype.QueryInterface = function(iid) {
- if (iid.equals(Components.interfaces.nsISupports) ||
- iid.equals(Components.interfaces.nsIUrlClassifierTable))
- return this;
-
- Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
- return null;
-}
-
-/**
- * Readonly count attribute.
- * @returns The number of keys in the map
- */
-G_Map.prototype.__defineGetter__('count', function() {
- return this.count_;
-});
diff --git a/toolkit/components/url-classifier/content/multi-querier.js b/toolkit/components/url-classifier/content/multi-querier.js
new file mode 100644
index 000000000000..64ff19270200
--- /dev/null
+++ b/toolkit/components/url-classifier/content/multi-querier.js
@@ -0,0 +1,145 @@
+/* ***** 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 Google Safe Browsing.
+ *
+ * The Initial Developer of the Original Code is Google Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Tony Chang (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 ***** */
+
+/**
+ * This class helps us batch a series of async calls to the db.
+ * If any of the tokens is in the database, we fire callback with
+ * true as a param. If all the tokens are not in the database,
+ * we fire callback with false as a param.
+ * This is an "Abstract" base class. Subclasses need to supply
+ * the condition_ method.
+ *
+ * @param tokens Array of strings to lookup in the db
+ * @param tableName String name of the table
+ * @param callback Function callback function that takes true if the condition
+ * passes.
+ */
+function MultiQuerier(tokens, tableName, callback) {
+ this.tokens_ = tokens;
+ this.tableName_ = tableName;
+ this.callback_ = callback;
+ this.dbservice_ = Cc["@mozilla.org/url-classifier/dbservice;1"]
+ .getService(Ci.nsIUrlClassifierDBService);
+ // We put the current token in this variable.
+ this.key_ = null;
+}
+
+/**
+ * Run the remaining tokens against the db.
+ */
+MultiQuerier.prototype.run = function() {
+ if (this.tokens_.length == 0) {
+ this.callback_.handleEvent(false);
+ return;
+ }
+
+ this.key_ = this.tokens_.pop();
+ G_Debug(this, "Looking up " + this.key_ + " in " + this.tableName_);
+ this.dbservice_.exists(this.tableName_, this.key_,
+ BindToObject(this.result_, this));
+}
+
+/**
+ * Callback from the db. If the returned value passes the this.condition_
+ * test, go ahead and call the main callback.
+ */
+MultiQuerier.prototype.result_ = function(value) {
+ if (this.condition_(value))
+ this.callback_.handleEvent(true)
+ else
+ this.run();
+}
+
+// Subclasses must override this.
+MultiQuerier.prototype.condition_ = function(value) {
+ throw "MultiQuerier is an abstract base class";
+}
+
+
+/**
+ * Concrete MultiQuerier that stops if the key exists in the db.
+ */
+function ExistsMultiQuerier(tokens, tableName, callback) {
+ MultiQuerier.call(this, tokens, tableName, callback);
+ this.debugZone = "existsMultiQuerier";
+}
+ExistsMultiQuerier.inherits(MultiQuerier);
+
+ExistsMultiQuerier.prototype.condition_ = function(value) {
+ return value.length > 0;
+}
+
+
+/**
+ * Concrete MultiQuerier that looks up a key, decrypts it, then
+ * checks the the resulting regular expressions for a match.
+ * @param tokens Array of hosts
+ */
+function EnchashMultiQuerier(tokens, tableName, callback, url) {
+ MultiQuerier.call(this, tokens, tableName, callback);
+ this.url_ = url;
+ this.enchashDecrypter_ = new PROT_EnchashDecrypter();
+ this.debugZone = "enchashMultiQuerier";
+}
+EnchashMultiQuerier.inherits(MultiQuerier);
+
+EnchashMultiQuerier.prototype.run = function() {
+ if (this.tokens_.length == 0) {
+ this.callback_.handleEvent(false);
+ return;
+ }
+ var host = this.tokens_.pop();
+ this.key_ = host;
+ var lookupKey = this.enchashDecrypter_.getLookupKey(host);
+ this.dbservice_.exists(this.tableName_, lookupKey,
+ BindToObject(this.result_, this));
+}
+
+EnchashMultiQuerier.prototype.condition_ = function(encryptedValue) {
+ if (encryptedValue.length > 0) {
+ // We have encrypted regular expressions for this host. Let's
+ // decrypt them and see if we have a match.
+ var decrypted = this.enchashDecrypter_.decryptData(encryptedValue,
+ this.key_);
+ var res = this.enchashDecrypter_.parseRegExps(decrypted);
+ for (var j = 0; j < res.length; j++) {
+ if (res[j].test(this.url_)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
diff --git a/toolkit/components/url-classifier/content/wireformat.js b/toolkit/components/url-classifier/content/wireformat.js
index 2d064495a22c..3e5e9b2be063 100644
--- a/toolkit/components/url-classifier/content/wireformat.js
+++ b/toolkit/components/url-classifier/content/wireformat.js
@@ -105,25 +105,34 @@ PROT_VersionParser.prototype.ImportVersion = function(version) {
this.mac = version.mac;
this.macFailed = version.macFailed;
this.macval = version.macval;
- // Don't set requireMac, since wfr creates vparsers from scratch and doesn't
+ // Don't set requireMac, since we create vparsers from scratch and doesn't
// know about it
}
/**
* Creates a string like [goog-white-black 1.1] from internal information
*
- * @returns version string
+ * @returns String
*/
PROT_VersionParser.prototype.toString = function() {
var s = "[" + this.type + " " + this.major + "." + this.minor + "]";
return s;
}
+/**
+ * Creates a string like 1.123 with the version number. This is the
+ * format we store in prefs.
+ * @return String
+ */
+PROT_VersionParser.prototype.versionString = function() {
+ return this.major + "." + this.minor;
+}
+
/**
* Creates a string like 1:1 from internal information used for
* fetching updates from the server. Called by the listmanager.
*
- * @returns version string
+ * @returns String
*/
PROT_VersionParser.prototype.toUrl = function() {
return this.major + ":" + this.minor;
diff --git a/toolkit/components/url-classifier/jar.mn b/toolkit/components/url-classifier/jar.mn
index 4ecdde0bd3f4..b43a34329393 100644
--- a/toolkit/components/url-classifier/jar.mn
+++ b/toolkit/components/url-classifier/jar.mn
@@ -2,8 +2,7 @@ toolkit.jar:
+ content/global/url-classifier/application.js (content/application.js)
+ content/global/url-classifier/enchash-decrypter.js (content/enchash-decrypter.js)
+ content/global/url-classifier/listmanager.js (content/listmanager.js)
-+ content/global/url-classifier/list-warden.js (content/list-warden.js)
-+ content/global/url-classifier/map.js (content/map.js)
++ content/global/url-classifier/multi-querier.js (content/multi-querier.js)
+ content/global/url-classifier/url-canonicalizer.js (content/url-canonicalizer.js)
+ content/global/url-classifier/url-crypto.js (content/url-crypto.js)
+ content/global/url-classifier/url-crypto-key-manager.js (content/url-crypto-key-manager.js)
diff --git a/toolkit/components/url-classifier/public/nsIUrlClassifierTable.idl b/toolkit/components/url-classifier/public/nsIUrlClassifierTable.idl
index ebd46eabe8e6..e58d5cf1b23f 100644
--- a/toolkit/components/url-classifier/public/nsIUrlClassifierTable.idl
+++ b/toolkit/components/url-classifier/public/nsIUrlClassifierTable.idl
@@ -36,15 +36,13 @@
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
+#include "nsIUrlListManager.idl"
// A map that contains a string keys mapped to string values.
-// TODO: maybe nsISerializeable to handle reading/writing from disk?
[scriptable, uuid(fd1f8334-1859-472d-b01f-4ac6b1121ce4)]
interface nsIUrlClassifierTable : nsISupports
{
- readonly attribute long count;
-
/**
* The name used to identify this table
*/
@@ -57,27 +55,9 @@ interface nsIUrlClassifierTable : nsISupports
/**
* In the simple case, exists just looks up the string in the
- * table and returns true if it is found. However, it could
- * do something more complex (e.g., canonicalize the url).
+ * table and call the callback after the query returns with true or
+ * false. It's possible that something more complex happens
+ * (e.g., canonicalize the url).
*/
- boolean exists(in ACString key);
-
- /**
- * In the simple case, key is a url and value is 1. However,
- * value could be more complicated (e.g., hashed value based
- * on site domain).
- */
- void insert(in ACString key, in ACString value);
-
- void remove(in ACString key);
-
- // TEMPORARY: used to help serialize the table to disk. May be removed.
- void getKeys(out unsigned long size,
- [retval,array,size_is(size)] out string keys);
-
- // TEMPORARY: used to help serialize the table to disk. May be removed.
- void findValue(in ACString key);
-
- // TODO: merge data
- // void replace(in nsIUrlClassifierTable);
+ void exists(in ACString key, in nsIUrlListManagerCallback cb);
};
diff --git a/toolkit/components/url-classifier/public/nsIUrlListManager.idl b/toolkit/components/url-classifier/public/nsIUrlListManager.idl
index 4bc8c6258126..3d4351f4413b 100644
--- a/toolkit/components/url-classifier/public/nsIUrlListManager.idl
+++ b/toolkit/components/url-classifier/public/nsIUrlListManager.idl
@@ -41,16 +41,15 @@
* Interface for a class that manages updates of multiple nsIUrlClassifierTables.
*/
-interface nsIFile;
+// Interface for JS function callbacks
+[scriptable, function, uuid(ba913c5c-13d6-41eb-83c1-de2f4165a516)]
+interface nsIUrlListManagerCallback : nsISupports {
+ void handleEvent(in boolean value);
+};
[scriptable, uuid(e1a80418-1bf9-4bd7-a40d-94d549c24955)]
interface nsIUrlListManager : nsISupports
{
- /**
- * Set the directory to read/write tables to.
- */
- void setAppDir(in nsIFile appDir);
-
/**
* Add a table to the list of tables we are managing. The name is a
* string of the format provider_name-semantic_type-table_type. For
@@ -71,21 +70,10 @@ interface nsIUrlListManager : nsISupports
void disableUpdate(in ACString tableName);
/**
- * Lookup a key in a table. Should not raise exceptions. Returns
- * true if the key was found into the table.
+ * Lookup a key in a table. Should not raise exceptions. Calls
+ * the callback function with a single parameter: true if the key
+ * is in the table, false if it isn't.
*/
- boolean safeExists(in ACString tableName, in ACString key);
-
- /**
- * Insert a key in a table. Should not raise exceptions. Returns
- * true if the key was inserted into the table.
- */
- boolean safeInsert(in ACString tableName, in ACString key,
- in ACString value);
-
- /**
- * Remove a key from a table. Should not raise exceptions. Returns
- * true if the key was removed from the table.
- */
- boolean safeRemove(in ACString tableName, in string key);
+ void safeExists(in ACString tableName, in ACString key,
+ in nsIUrlListManagerCallback cb);
};
diff --git a/toolkit/components/url-classifier/src/Makefile.in b/toolkit/components/url-classifier/src/Makefile.in
index 95da84a161cd..a63522ef98c8 100644
--- a/toolkit/components/url-classifier/src/Makefile.in
+++ b/toolkit/components/url-classifier/src/Makefile.in
@@ -29,7 +29,6 @@ LOCAL_INCLUDES = \
# EXTRA_COMPONENTS installs components written in JS to dist/bin/components
EXTRA_COMPONENTS = urlClassifierTableUrl.js \
urlClassifierTableDomain.js \
- urlClassifierTableSite.js \
urlClassifierTableEnchash.js \
urlListManager.js \
$(NULL)
diff --git a/toolkit/components/url-classifier/src/nsUrlClassifierDBService.cpp b/toolkit/components/url-classifier/src/nsUrlClassifierDBService.cpp
index 08b609d0097f..ff7f9253c29a 100644
--- a/toolkit/components/url-classifier/src/nsUrlClassifierDBService.cpp
+++ b/toolkit/components/url-classifier/src/nsUrlClassifierDBService.cpp
@@ -340,7 +340,7 @@ nsUrlClassifierDBServiceWorker::ProcessUpdateTable(
nsresult rv = NS_ERROR_FAILURE;
if ('+' == op && spacePos != kNotFound) {
- // Insert operation of the form "+KEY VALUE"
+ // Insert operation of the form "+KEY\tVALUE"
const nsDependentCSubstring &key = Substring(aLine, 1, spacePos - 1);
const nsDependentCSubstring &value = Substring(aLine, spacePos + 1);
aUpdateStatement->BindUTF8StringParameter(0, key);
diff --git a/toolkit/components/url-classifier/src/urlClassifierTableDomain.js b/toolkit/components/url-classifier/src/urlClassifierTableDomain.js
index 7ec723f528b0..69b60286803b 100644
--- a/toolkit/components/url-classifier/src/urlClassifierTableDomain.js
+++ b/toolkit/components/url-classifier/src/urlClassifierTableDomain.js
@@ -1,3 +1,43 @@
+/* ***** 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 Url Classifier code
+ *
+ * The Initial Developer of the Original Code is
+ * Google Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Tony Chang
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 ***** */
+
+// TODO: Combine this file with other urlClassifierTable files and rename to
+// nsUrlClassifierTable.js
+
const Cc = Components.classes;
const Ci = Components.interfaces;
const G_GDEBUG = false;
@@ -11,8 +51,9 @@ const LIB_FILES = [
"chrome://global/content/url-classifier/moz/preferences.js",
"chrome://global/content/url-classifier/moz/filesystem.js",
"chrome://global/content/url-classifier/moz/debug.js", // req js/lang.js moz/prefs.js moz/filesystem.js
+ "chrome://global/content/url-classifier/moz/lang.js",
- "chrome://global/content/url-classifier/map.js",
+ "chrome://global/content/url-classifier/multi-querier.js",
];
for (var i = 0, libFile; libFile = LIB_FILES[i]; ++i) {
@@ -23,18 +64,25 @@ for (var i = 0, libFile; libFile = LIB_FILES[i]; ++i) {
}
function UrlClassifierTableDomain() {
- G_Map.call(this);
this.debugZone = "trtable-domain";
+ this.name = '';
+ this.needsUpdate = false;
}
-UrlClassifierTableDomain.inherits(G_Map);
-
+UrlClassifierTableDomain.prototype.QueryInterface = function(iid) {
+ if (iid.equals(Components.interfaces.nsISupports) ||
+ iid.equals(Components.interfaces.nsIUrlClassifierTable))
+ return this;
+ Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
+ return null;
+}
+
/**
* Look up a URL in a domain table
*
* @returns Boolean true if the url domain is in the table
*/
-UrlClassifierTableDomain.prototype.exists = function(url) {
+UrlClassifierTableDomain.prototype.exists = function(url, callback) {
var urlObj = Cc["@mozilla.org/network/standard-url;1"]
.createInstance(Ci.nsIURL);
urlObj.spec = url;
@@ -43,13 +91,14 @@ UrlClassifierTableDomain.prototype.exists = function(url) {
// We don't have a good way map from hosts to domains, so we instead try
// each possibility. Could probably optimize to start at the second dot?
+ var possible = [];
for (var i = 0; i < components.length - 1; i++) {
host = components.slice(i).join(".");
- var val = this.find_(host);
- if (val)
- return true;
+ possible.push(host);
}
- return false;
+
+ // Run the possible domains against the db.
+ (new ExistsMultiQuerier(possible, this.name, callback)).run();
}
diff --git a/toolkit/components/url-classifier/src/urlClassifierTableEnchash.js b/toolkit/components/url-classifier/src/urlClassifierTableEnchash.js
index fd6492efa9b5..4988518f7b72 100644
--- a/toolkit/components/url-classifier/src/urlClassifierTableEnchash.js
+++ b/toolkit/components/url-classifier/src/urlClassifierTableEnchash.js
@@ -1,3 +1,43 @@
+/* ***** 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 Url Classifier code
+ *
+ * The Initial Developer of the Original Code is
+ * Google Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Tony Chang
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 ***** */
+
+// TODO: Combine this file with other urlClassifierTable files and rename to
+// nsUrlClassifierTable.js
+
const Cc = Components.classes;
const Ci = Components.interfaces;
const G_GDEBUG = false;
@@ -12,11 +52,12 @@ const LIB_FILES = [
"chrome://global/content/url-classifier/moz/preferences.js",
"chrome://global/content/url-classifier/moz/filesystem.js",
"chrome://global/content/url-classifier/moz/debug.js", // req js/lang.js moz/prefs.js moz/filesystem.js
+ "chrome://global/content/url-classifier/moz/lang.js",
- "chrome://global/content/url-classifier/map.js",
"chrome://global/content/url-classifier/moz/base64.js",
"chrome://global/content/url-classifier/moz/cryptohasher.js",
"chrome://global/content/url-classifier/enchash-decrypter.js",
+ "chrome://global/content/url-classifier/multi-querier.js",
];
for (var i = 0, libFile; libFile = LIB_FILES[i]; ++i) {
@@ -27,45 +68,39 @@ for (var i = 0, libFile; libFile = LIB_FILES[i]; ++i) {
}
function UrlClassifierTableEnchash() {
- G_Map.call(this);
this.debugZone = "trtable-enchash";
+ this.dbservice = Cc["@mozilla.org/url-classifier/dbservice;1"]
+ .getService(Ci.nsIUrlClassifierDBService);
+ this.name = '';
+ this.needsUpdate = false;
this.enchashDecrypter_ = new PROT_EnchashDecrypter();
}
-UrlClassifierTableEnchash.inherits(G_Map);
+UrlClassifierTableEnchash.prototype.QueryInterface = function(iid) {
+ if (iid.equals(Components.interfaces.nsISupports) ||
+ iid.equals(Components.interfaces.nsIUrlClassifierTable))
+ return this;
+ Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
+ return null;
+}
/**
* Look up a URL in an enchashDB
- *
- * @returns Boolean indicating whether the URL matches the regular
- * expression contained in the table value
*/
-UrlClassifierTableEnchash.prototype.exists = function(url) {
+UrlClassifierTableEnchash.prototype.exists = function(url, callback) {
var host = this.enchashDecrypter_.getCanonicalHost(url);
+ var possible = [];
for (var i = 0; i < PROT_EnchashDecrypter.MAX_DOTS + 1; i++) {
- var key = this.enchashDecrypter_.getLookupKey(host);
-
- var encrypted = this.find_(key);
- if (encrypted) {
- G_Debug(this, "Enchash DB has host " + host);
-
- // We have encrypted regular expressions for this host. Let's
- // decrypt them and see if we have a match.
- var decrypted = this.enchashDecrypter_.decryptData(encrypted, host);
- var res = this.enchashDecrypter_.parseRegExps(decrypted);
- for (var j = 0; j < res.length; j++) {
- if (res[j].test(url))
- return true;
- }
- }
+ possible.push(host);
var index = host.indexOf(".");
if (index == -1)
break;
host = host.substring(index + 1);
}
- return false;
+ // Run the possible domains against the db.
+ (new EnchashMultiQuerier(possible, this.name, callback, url)).run();
}
diff --git a/toolkit/components/url-classifier/src/urlClassifierTableSite.js b/toolkit/components/url-classifier/src/urlClassifierTableSite.js
deleted file mode 100644
index 4a950bc88593..000000000000
--- a/toolkit/components/url-classifier/src/urlClassifierTableSite.js
+++ /dev/null
@@ -1,118 +0,0 @@
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const G_GDEBUG = false;
-
-// Use subscript loader to load files. The files in ../content get mapped
-// to chrome://global/content/url-classifier/. Order matters if one file depends
-// on another file during initialization.
-const LIB_FILES = [
- "chrome://global/content/url-classifier/js/lang.js",
-
- "chrome://global/content/url-classifier/moz/preferences.js",
- "chrome://global/content/url-classifier/moz/filesystem.js",
- "chrome://global/content/url-classifier/moz/debug.js", // req js/lang.js moz/prefs.js moz/filesystem.js
-
- "chrome://global/content/url-classifier/map.js",
-];
-
-for (var i = 0, libFile; libFile = LIB_FILES[i]; ++i) {
- //dump('*** loading subscript ' + libFile + '\n');
- Cc["@mozilla.org/moz/jssubscript-loader;1"]
- .getService(Ci.mozIJSSubScriptLoader)
- .loadSubScript(libFile);
-}
-
-function UrlClassifierTableSite() {
- G_Map.call(this);
- this.debugZone = "trtable-site";
- this.ioService_ = Cc["@mozilla.org/network/io-service;1"]
- .getService(Ci.nsIIOService);
-}
-
-UrlClassifierTableSite.inherits(G_Map);
-
-/**
- * Look up a URL in a site DB
- *
- * @returns Boolean true if URL matches in table, we normalize based on
- * part of the path
- */
-UrlClassifierTableSite.prototype.exists = function(url) {
- var nsIURI = this.ioService_.newURI(url, null, null);
- var host = nsIURI.asciiHost;
- var hostComponents = host.split(".");
-
- var path = nsIURI.path;
- var pathComponents = path.split("/");
-
- // We don't have a good way to convert a fully specified URL into a
- // site. We try host name components with or without the first
- // path component.
- for (var i = 0; i < hostComponents.length - 1; i++) {
- host = hostComponents.slice(i).join(".") + "/";
- var val = this.find_(host);
- G_Debug(this, "Checking: " + host + " : " + val);
- if (val)
- return true;
-
- // The path starts with a "/", so we are interested in the second path
- // component if it is available
- if (pathComponents.length >= 2) {
- host = host + pathComponents[1] + "/";
- var val = this.find_(host);
- G_Debug(this, "Checking: " + host + " : " + val);
- if (val)
- return true;
- }
- }
-
- return false;
-}
-
-// Module object
-function UrlClassifierTableSiteMod() {
- this.firstTime = true;
- this.cid = Components.ID("{1e48f217-34e4-44a3-9b4a-9b66ed0a1201}");
- this.progid = "@mozilla.org/url-classifier/table;1?type=site";
-}
-
-UrlClassifierTableSiteMod.prototype.registerSelf = function(compMgr, fileSpec, loc, type) {
- if (this.firstTime) {
- this.firstTime = false;
- throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
- }
- compMgr = compMgr.QueryInterface(Ci.nsIComponentRegistrar);
- compMgr.registerFactoryLocation(this.cid,
- "UrlClassifier Table Site Module",
- this.progid,
- fileSpec,
- loc,
- type);
-};
-
-UrlClassifierTableSiteMod.prototype.getClassObject = function(compMgr, cid, iid) {
- if (!cid.equals(this.cid))
- throw Components.results.NS_ERROR_NO_INTERFACE;
- if (!iid.equals(Ci.nsIFactory))
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
-
- return this.factory;
-}
-
-UrlClassifierTableSiteMod.prototype.canUnload = function(compMgr) {
- return true;
-}
-
-UrlClassifierTableSiteMod.prototype.factory = {
- createInstance: function(outer, iid) {
- if (outer != null)
- throw Components.results.NS_ERROR_NO_AGGREGATION;
- return (new UrlClassifierTableSite()).QueryInterface(iid);
- }
-};
-
-var SiteModInst = new UrlClassifierTableSiteMod();
-
-function NSGetModule(compMgr, fileSpec) {
- return SiteModInst;
-}
diff --git a/toolkit/components/url-classifier/src/urlClassifierTableUrl.js b/toolkit/components/url-classifier/src/urlClassifierTableUrl.js
index a79684920a94..21d389aa6a21 100644
--- a/toolkit/components/url-classifier/src/urlClassifierTableUrl.js
+++ b/toolkit/components/url-classifier/src/urlClassifierTableUrl.js
@@ -1,3 +1,43 @@
+/* ***** 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 Url Classifier code
+ *
+ * The Initial Developer of the Original Code is
+ * Google Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Tony Chang
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 ***** */
+
+// TODO: Combine this file with other urlClassifierTable files and rename to
+// nsUrlClassifierTable.js
+
const Cc = Components.classes;
const Ci = Components.interfaces;
const G_GDEBUG = false;
@@ -12,7 +52,6 @@ const LIB_FILES = [
"chrome://global/content/url-classifier/moz/filesystem.js",
"chrome://global/content/url-classifier/moz/debug.js", // req js/lang.js moz/prefs.js moz/filesystem.js
- "chrome://global/content/url-classifier/map.js",
"chrome://global/content/url-classifier/url-canonicalizer.js"
];
@@ -24,22 +63,33 @@ for (var i = 0, libFile; libFile = LIB_FILES[i]; ++i) {
}
function UrlClassifierTableUrl() {
- G_Map.call(this);
this.debugZone = "trtable-url";
+ this.dbservice_ = Cc["@mozilla.org/url-classifier/dbservice;1"]
+ .getService(Ci.nsIUrlClassifierDBService);
+ this.name = '';
+ this.needsUpdate = false;
}
-UrlClassifierTableUrl.inherits(G_Map);
+UrlClassifierTableUrl.prototype.QueryInterface = function(iid) {
+ if (iid.equals(Components.interfaces.nsISupports) ||
+ iid.equals(Components.interfaces.nsIUrlClassifierTable))
+ return this;
+ Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
+ return null;
+}
/**
* Look up a URL in a URL table
- *
- * @returns Boolean true if the canonicalized url is in the table
*/
-UrlClassifierTableUrl.prototype.exists = function(url) {
+UrlClassifierTableUrl.prototype.exists = function(url, callback) {
var canonicalized = PROT_URLCanonicalizer.canonicalizeURL_(url);
- // Uncomment for debugging
G_Debug(this, "Looking up: " + url + " (" + canonicalized + ")");
- return this.find_(canonicalized);
+
+ function dbCallback(v) {
+ G_Debug("dbCallback", "Looked up " + url + ": " + v + "|");
+ callback.handleEvent(v.length > 0);
+ }
+ this.dbservice_.exists(this.name, url, dbCallback);
}
diff --git a/toolkit/components/url-classifier/src/urlListManager.js b/toolkit/components/url-classifier/src/urlListManager.js
index cd3ab530e39c..633311f62e66 100644
--- a/toolkit/components/url-classifier/src/urlListManager.js
+++ b/toolkit/components/url-classifier/src/urlListManager.js
@@ -1,6 +1,45 @@
+/* ***** 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 Url Classifier code
+ *
+ * The Initial Developer of the Original Code is
+ * Google Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Tony Chang
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 ***** */
+
+// TODO: Rename this file to nsUrlClassifierListManager.js
+
const Cc = Components.classes;
const Ci = Components.interfaces;
-const G_GDEBUG = true;
+const G_GDEBUG = false;
// Use subscript loader to load files. The files in ../content get mapped
// to chrome://global/content/url-classifier/. Order matters if one file depends