Bug 336694 (for tony@ponderer.org) r=ben use url-classifier db service for local list management

This commit is contained in:
brettw%gmail.com 2006-05-05 21:51:46 +00:00
Родитель 4db436d5f2
Коммит f94d228c92
19 изменённых файлов: 532 добавлений и 897 удалений

Просмотреть файл

@ -267,7 +267,7 @@
</button> </button>
<image id="lock-icon" onclick="if (event.button == 0) displaySecurityInfo(); event.stopPropagation();"/> <image id="lock-icon" onclick="if (event.button == 0) displaySecurityInfo(); event.stopPropagation();"/>
#ifdef MOZ_SAFE_BROWSING #ifdef MOZ_SAFE_BROWSING
<image src="chrome://browser/content/safebrowsing/skin/warning16x16.png" <image src="chrome://browser/skin/safebrowsing/warning16x16.png"
id="safebrowsing-urlbar-icon" tooltiptext="&safeb.urlbaricon.tooltip;" id="safebrowsing-urlbar-icon" tooltiptext="&safeb.urlbaricon.tooltip;"
style="display:none" style="display:none"
onclick="goDoCommand('safebrowsing-show-warning')" /> onclick="goDoCommand('safebrowsing-show-warning')" />

Просмотреть файл

@ -131,109 +131,104 @@ PROT_ListWarden.prototype.registerWhiteTable = function(tableName) {
return result; 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. * 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. * 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 * @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) { PROT_ListWarden.prototype.isEvilURL_ = function(url, evilCallback) {
return !this.isWhiteURL_(url) && this.isBlackURL_(url); (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() { // Since we pop from whiteTables_ and blackTables_, we need to make a copy.
if (G_GDEBUG) { this.whiteTables_ = [];
var z = "listwarden UNITTEST"; this.blackTables_ = [];
G_debugService.enableZone(z); for (var i = 0; i < whiteTables.length; ++i) {
G_Debug(z, "Starting"); this.whiteTables_.push(whiteTables[i]);
}
for (var i = 0; i < blackTables.length; ++i) {
this.blackTables_.push(blackTables[i]);
}
var threadQueue = new TH_ThreadQueue(); this.evilCallback_ = evilCallback;
var listManager = new PROT_ListManager(threadQueue, true /* testing */); this.listManager_ = Cc["@mozilla.org/url-classifier/listmanager;1"]
.getService(Ci.nsIUrlListManager);
var warden = new PROT_ListWarden(listManager); }
// Just some really simple test /**
G_Assert(z, warden.registerWhiteTable("test-white-domain"), * We first query the white tables in succession. If any contain
"Failed to register test-white-domain table"); * the url, we stop. If none contain the url, we query the black tables
G_Assert(z, warden.registerWhiteTable("test-black-url"), * in succession. If any contain the url, we call evilCallback and
"Failed to register test-black-url table"); * stop. If none of the black tables contain the url, then we just stop
listManager.safeInsert("test-white-domain", "http://foo.com/good", "1"); * (i.e., it's not black url).
listManager.safeInsert("test-black-url", "http://foo.com/good/1", "1"); */
listManager.safeInsert("test-black-url", "http://foo.com/bad/1", "1"); MultiTableQuerier.prototype.run = function() {
if (this.whiteTables_.length > 0) {
G_Assert(z, !warden.isEvilURL_("http://foo.com/good/1"), var tableName = this.whiteTables_.pop();
"White listing is not working."); G_Debug(this, "Looking in whitetable: " + tableName);
G_Assert(z, warden.isEvilURL_("http://foo.com/bad/1"), this.listManager_.safeExists(tableName, this.url_,
"Black listing is not working."); BindToObject(this.whiteTableCallback_,
this));
G_Debug(z, "PASSED"); } 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_();
} }
} }

Просмотреть файл

@ -266,20 +266,15 @@ PROT_PhishingWarden.prototype.onDocNavStart = function(e) {
// We're enabled. Either send a request off or check locally // We're enabled. Either send a request off or check locally
// TODO: move this logic to checkUrl, formalize the error callback // TODO: move this logic to checkUrl, formalize the error callback
if (this.checkRemote_) { if (this.checkRemote_) {
// Use local whitelists to suppress remote BL lookups. // TODO: Use local whitelists to suppress remote BL lookups.
if (!this.isWhiteURL_(url)) { this.fetcher_.get(url,
G_Debug(this, "Local whitelist lookup failed"); BindToObject(this.onTRFetchComplete,
this.fetcher_.get(url, this,
BindToObject(this.onTRFetchComplete, request));
this,
request));
} else {
G_Debug(this, "WL suppressing BL lookup for " + url);
}
} else { } else {
if (this.checkUrl(url)) { this.checkUrl(url, BindToObject(this.houstonWeHaveAProblem_,
this.houstonWeHaveAProblem_(request); this,
} request));
} }
} }
} }
@ -432,22 +427,26 @@ PROT_PhishingWarden.prototype.isBlacklistTestURL = function(url) {
/** /**
* Look the URL up in our local blacklists * Look the URL up in our local blacklists
* *
* @param url URL to check
* @param callback Function to invoke if there is a problem. * @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); G_Debug(this, "Checking URL for " + url);
if (this.isBlacklistTestURL(url)) {
if (this.isEvilURL_(url) || this.isBlacklistTestURL(url)) { callback();
G_Debug(this, "Local blacklist hit"); } else {
// maybe send a report // We wrap the callback because we also want
(new PROT_Reporter).report("phishblhit", url); // to report the blacklist hit to our data provider.
return true; 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;
} }
/** /**

Просмотреть файл

@ -1,6 +1,6 @@
const Cc = Components.classes; const Cc = Components.classes;
const Ci = Components.interfaces; const Ci = Components.interfaces;
const G_GDEBUG = true; const G_GDEBUG = false;
// Use subscript loader to load files. The files in ../content get mapped // Use subscript loader to load files. The files in ../content get mapped
// to chrome://browser/content/safebrowsing/. Order matters if one file depends // to chrome://browser/content/safebrowsing/. Order matters if one file depends

Просмотреть файл

@ -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 <niels@google.com> (original author)d
* Fritz Schneider <fritz@google.com>
*
* 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");
}
}

Просмотреть файл

@ -268,65 +268,21 @@ PROT_ListManager.prototype.stopUpdateChecker = function() {
* use this because at certain points our tables might not be loaded, * use this because at certain points our tables might not be loaded,
* and querying them could throw. * and querying them could throw.
* *
* @param table Name of the table that we want to consult * @param table String Name of the table that we want to consult
* @param key Key for table lookup * @param key String Key for table lookup
* @returns false or the value in the table corresponding to key. * @param callback nsIUrlListManagerCallback (ie., Function) given false or the
* If the table name does not exist, we return false, too. * 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) { PROT_ListManager.prototype.safeExists = function(table, key, callback) {
var result = false;
try { try {
G_Debug(this, "safeExists: " + table + ", " + key);
var map = this.tablesData[table]; var map = this.tablesData[table];
result = map.exists(key); map.exists(key, callback);
} catch(e) { } catch(e) {
result = false;
G_Debug(this, "safeExists masked failure for " + table + ", key " + key + ": " + e); 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 * Callback from db update service. As new tables are added to the db,
* "[goog-white-url 1.1234 update]" and set the version numbers in the user * this callback is fired so we can update the version number.
* pref. * @param versionString String containing the table update response from the
* @param updateString String containing the response from the server. * server
* @return Array a list of table names
*/ */
PROT_ListManager.prototype.setTableVersions_ = function(updateString) { PROT_ListManager.prototype.setTableVersion_ = function(versionString) {
var updatedTables = []; 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; this.prefs_.setPref(prefBase + tableName, versionNumber);
var startPos = updateString.indexOf('[');
var endPos; if (!this.tablesKnown_[tableName]) {
while (startPos != -1) { this.tablesKnown_[tableName] = versionParser;
// [ needs to be the start of a new line } else {
if (0 == startPos || ('\n' == updateString[startPos - 1] && this.tablesKnown_[tableName].ImportVersion(versionParser);
'\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 could catch option params, but that's ok. The double newline
// check will skip over it. if (!this.tablesData[tableName])
startPos = updateString.indexOf('[', startPos + 1); this.tablesData[tableName] = newUrlClassifierTable(tableName);
} }
return updatedTables;
} }
/** /**
@ -485,32 +428,12 @@ PROT_ListManager.prototype.rpcDone = function(data) {
return; 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"] var dbUpdateSrv = Cc["@mozilla.org/url-classifier/dbservice;1"]
.getService(Ci.nsIUrlClassifierDBService); .getService(Ci.nsIUrlClassifierDBService);
// Update the tables on disk. // Update the tables on disk in a background thread. Multiple updates
try { // will be queue up.
dbUpdateSrv.updateTables(data); dbUpdateSrv.updateTables(data, BindToObject(this.setTableVersion_, this));
} 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);
}
} }
/** /**

Просмотреть файл

@ -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 <fritz@google.com> (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_;
});

Просмотреть файл

@ -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 <tony@google.com> (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;
}

Просмотреть файл

@ -105,25 +105,34 @@ PROT_VersionParser.prototype.ImportVersion = function(version) {
this.mac = version.mac; this.mac = version.mac;
this.macFailed = version.macFailed; this.macFailed = version.macFailed;
this.macval = version.macval; 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 // know about it
} }
/** /**
* Creates a string like [goog-white-black 1.1] from internal information * Creates a string like [goog-white-black 1.1] from internal information
* *
* @returns version string * @returns String
*/ */
PROT_VersionParser.prototype.toString = function() { PROT_VersionParser.prototype.toString = function() {
var s = "[" + this.type + " " + this.major + "." + this.minor + "]"; var s = "[" + this.type + " " + this.major + "." + this.minor + "]";
return s; 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 * Creates a string like 1:1 from internal information used for
* fetching updates from the server. Called by the listmanager. * fetching updates from the server. Called by the listmanager.
* *
* @returns version string * @returns String
*/ */
PROT_VersionParser.prototype.toUrl = function() { PROT_VersionParser.prototype.toUrl = function() {
return this.major + ":" + this.minor; return this.major + ":" + this.minor;

Просмотреть файл

@ -2,8 +2,7 @@ toolkit.jar:
+ content/global/url-classifier/application.js (content/application.js) + content/global/url-classifier/application.js (content/application.js)
+ content/global/url-classifier/enchash-decrypter.js (content/enchash-decrypter.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/listmanager.js (content/listmanager.js)
+ content/global/url-classifier/list-warden.js (content/list-warden.js) + content/global/url-classifier/multi-querier.js (content/multi-querier.js)
+ content/global/url-classifier/map.js (content/map.js)
+ content/global/url-classifier/url-canonicalizer.js (content/url-canonicalizer.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.js (content/url-crypto.js)
+ content/global/url-classifier/url-crypto-key-manager.js (content/url-crypto-key-manager.js) + content/global/url-classifier/url-crypto-key-manager.js (content/url-crypto-key-manager.js)

Просмотреть файл

@ -36,15 +36,13 @@
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl" #include "nsISupports.idl"
#include "nsIUrlListManager.idl"
// A map that contains a string keys mapped to string values. // 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)] [scriptable, uuid(fd1f8334-1859-472d-b01f-4ac6b1121ce4)]
interface nsIUrlClassifierTable : nsISupports interface nsIUrlClassifierTable : nsISupports
{ {
readonly attribute long count;
/** /**
* The name used to identify this table * 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 * In the simple case, exists just looks up the string in the
* table and returns true if it is found. However, it could * table and call the callback after the query returns with true or
* do something more complex (e.g., canonicalize the url). * false. It's possible that something more complex happens
* (e.g., canonicalize the url).
*/ */
boolean exists(in ACString key); void exists(in ACString key, in nsIUrlListManagerCallback cb);
/**
* 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);
}; };

Просмотреть файл

@ -41,16 +41,15 @@
* Interface for a class that manages updates of multiple nsIUrlClassifierTables. * 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)] [scriptable, uuid(e1a80418-1bf9-4bd7-a40d-94d549c24955)]
interface nsIUrlListManager : nsISupports 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 * 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 * string of the format provider_name-semantic_type-table_type. For
@ -71,21 +70,10 @@ interface nsIUrlListManager : nsISupports
void disableUpdate(in ACString tableName); void disableUpdate(in ACString tableName);
/** /**
* Lookup a key in a table. Should not raise exceptions. Returns * Lookup a key in a table. Should not raise exceptions. Calls
* true if the key was found into the table. * 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); void safeExists(in ACString tableName, in ACString key,
in nsIUrlListManagerCallback cb);
/**
* 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);
}; };

Просмотреть файл

@ -29,7 +29,6 @@ LOCAL_INCLUDES = \
# EXTRA_COMPONENTS installs components written in JS to dist/bin/components # EXTRA_COMPONENTS installs components written in JS to dist/bin/components
EXTRA_COMPONENTS = urlClassifierTableUrl.js \ EXTRA_COMPONENTS = urlClassifierTableUrl.js \
urlClassifierTableDomain.js \ urlClassifierTableDomain.js \
urlClassifierTableSite.js \
urlClassifierTableEnchash.js \ urlClassifierTableEnchash.js \
urlListManager.js \ urlListManager.js \
$(NULL) $(NULL)

Просмотреть файл

@ -340,7 +340,7 @@ nsUrlClassifierDBServiceWorker::ProcessUpdateTable(
nsresult rv = NS_ERROR_FAILURE; nsresult rv = NS_ERROR_FAILURE;
if ('+' == op && spacePos != kNotFound) { 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 &key = Substring(aLine, 1, spacePos - 1);
const nsDependentCSubstring &value = Substring(aLine, spacePos + 1); const nsDependentCSubstring &value = Substring(aLine, spacePos + 1);
aUpdateStatement->BindUTF8StringParameter(0, key); aUpdateStatement->BindUTF8StringParameter(0, key);

Просмотреть файл

@ -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 <tony@ponderer.org>
*
* 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 Cc = Components.classes;
const Ci = Components.interfaces; const Ci = Components.interfaces;
const G_GDEBUG = false; 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/preferences.js",
"chrome://global/content/url-classifier/moz/filesystem.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/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) { 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() { function UrlClassifierTableDomain() {
G_Map.call(this);
this.debugZone = "trtable-domain"; 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 * Look up a URL in a domain table
* *
* @returns Boolean true if the url domain is in the 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"] var urlObj = Cc["@mozilla.org/network/standard-url;1"]
.createInstance(Ci.nsIURL); .createInstance(Ci.nsIURL);
urlObj.spec = url; 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 // 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? // each possibility. Could probably optimize to start at the second dot?
var possible = [];
for (var i = 0; i < components.length - 1; i++) { for (var i = 0; i < components.length - 1; i++) {
host = components.slice(i).join("."); host = components.slice(i).join(".");
var val = this.find_(host); possible.push(host);
if (val)
return true;
} }
return false;
// Run the possible domains against the db.
(new ExistsMultiQuerier(possible, this.name, callback)).run();
} }

Просмотреть файл

@ -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 <tony@ponderer.org>
*
* 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 Cc = Components.classes;
const Ci = Components.interfaces; const Ci = Components.interfaces;
const G_GDEBUG = false; 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/preferences.js",
"chrome://global/content/url-classifier/moz/filesystem.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/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/base64.js",
"chrome://global/content/url-classifier/moz/cryptohasher.js", "chrome://global/content/url-classifier/moz/cryptohasher.js",
"chrome://global/content/url-classifier/enchash-decrypter.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) { 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() { function UrlClassifierTableEnchash() {
G_Map.call(this);
this.debugZone = "trtable-enchash"; 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(); 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 * 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 host = this.enchashDecrypter_.getCanonicalHost(url);
var possible = [];
for (var i = 0; i < PROT_EnchashDecrypter.MAX_DOTS + 1; i++) { for (var i = 0; i < PROT_EnchashDecrypter.MAX_DOTS + 1; i++) {
var key = this.enchashDecrypter_.getLookupKey(host); possible.push(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;
}
}
var index = host.indexOf("."); var index = host.indexOf(".");
if (index == -1) if (index == -1)
break; break;
host = host.substring(index + 1); host = host.substring(index + 1);
} }
return false; // Run the possible domains against the db.
(new EnchashMultiQuerier(possible, this.name, callback, url)).run();
} }

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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 <tony@ponderer.org>
*
* 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 Cc = Components.classes;
const Ci = Components.interfaces; const Ci = Components.interfaces;
const G_GDEBUG = false; 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/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/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" "chrome://global/content/url-classifier/url-canonicalizer.js"
]; ];
@ -24,22 +63,33 @@ for (var i = 0, libFile; libFile = LIB_FILES[i]; ++i) {
} }
function UrlClassifierTableUrl() { function UrlClassifierTableUrl() {
G_Map.call(this);
this.debugZone = "trtable-url"; 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 * 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); var canonicalized = PROT_URLCanonicalizer.canonicalizeURL_(url);
// Uncomment for debugging
G_Debug(this, "Looking up: " + url + " (" + canonicalized + ")"); 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);
} }

Просмотреть файл

@ -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 <tony@ponderer.org>
*
* 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 Cc = Components.classes;
const Ci = Components.interfaces; const Ci = Components.interfaces;
const G_GDEBUG = true; const G_GDEBUG = false;
// Use subscript loader to load files. The files in ../content get mapped // Use subscript loader to load files. The files in ../content get mapped
// to chrome://global/content/url-classifier/. Order matters if one file depends // to chrome://global/content/url-classifier/. Order matters if one file depends