зеркало из https://github.com/mozilla/gecko-dev.git
Bug 336694 (for tony@ponderer.org) r=ben use url-classifier db service for local list management
This commit is contained in:
Родитель
4db436d5f2
Коммит
f94d228c92
|
@ -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
|
||||||
|
|
Загрузка…
Ссылка в новой задаче