mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
bug 340603: getting table updates consumes large amounts of memory
patch: interface for streaming updates r+a=darin
This commit is contained in:
parent
77d2863c98
commit
788b00d2ae
@ -77,6 +77,9 @@
|
||||
#define NS_URLCLASSIFIERDBSERVICE_CONTRACTID \
|
||||
"@mozilla.org/url-classifier/dbservice;1"
|
||||
|
||||
#define NS_URLCLASSIFIERSTREAMUPDATER_CONTRACTID \
|
||||
"@mozilla.org/url-classifier/streamupdater;1"
|
||||
|
||||
#define NS_SCRIPTABLEUNESCAPEHTML_CONTRACTID "@mozilla.org/feed-unescapehtml;1"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@ -119,9 +122,15 @@
|
||||
// {e7f70966-9a37-48d7-8aeb-35998f31090e}
|
||||
#define NS_TYPEAHEADFIND_CID \
|
||||
{ 0xe7f70966, 0x9a37, 0x48d7, { 0x8a, 0xeb, 0x35, 0x99, 0x8f, 0x31, 0x09, 0x0e} }
|
||||
|
||||
|
||||
// {5eb7c3c1-ec1f-4007-87cc-eefb37d68ce6}
|
||||
#define NS_URLCLASSIFIERDBSERVICE_CID \
|
||||
{ 0x5eb7c3c1, 0xec1f, 0x4007, { 0x87, 0xcc, 0xee, 0xfb, 0x37, 0xd6, 0x8c, 0xe6} }
|
||||
|
||||
// {c2be6dc0-ef1e-4abd-86a2-4f864ddc57f6}
|
||||
#define NS_URLCLASSIFIERSTREAMUPDATER_CID \
|
||||
{ 0xc2be6dc0, 0xef1e, 0x4abd, { 0x86, 0xa2, 0x4f, 0x86, 0x4d, 0xdc, 0x57, 0xf6} }
|
||||
|
||||
// {10f2f5f0-f103-4901-980f-ba11bd70d60d}
|
||||
#define NS_SCRIPTABLEUNESCAPEHTML_CID \
|
||||
{ 0x10f2f5f0, 0xf103, 0x4901, { 0x98, 0x0f, 0xba, 0x11, 0xbd, 0x70, 0xd6, 0x0d} }
|
||||
|
@ -56,6 +56,7 @@
|
||||
|
||||
#ifdef MOZ_URL_CLASSIFIER
|
||||
#include "nsUrlClassifierDBService.h"
|
||||
#include "nsUrlClassifierStreamUpdater.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_FEEDS
|
||||
@ -84,6 +85,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsTypeAheadFind)
|
||||
#ifdef MOZ_URL_CLASSIFIER
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsUrlClassifierDBService,
|
||||
nsUrlClassifierDBService::GetInstance)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsUrlClassifierStreamUpdater)
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_FEEDS
|
||||
@ -132,6 +134,10 @@ static const nsModuleComponentInfo components[] =
|
||||
NS_URLCLASSIFIERDBSERVICE_CID,
|
||||
NS_URLCLASSIFIERDBSERVICE_CONTRACTID,
|
||||
nsUrlClassifierDBServiceConstructor },
|
||||
{ "Url Classifier Stream Updater",
|
||||
NS_URLCLASSIFIERSTREAMUPDATER_CID,
|
||||
NS_URLCLASSIFIERSTREAMUPDATER_CONTRACTID,
|
||||
nsUrlClassifierStreamUpdaterConstructor },
|
||||
#endif
|
||||
#ifdef MOZ_FEEDS
|
||||
{ "Unescape HTML",
|
||||
|
@ -9,6 +9,7 @@ MODULE = url-classifier
|
||||
XPIDL_MODULE = url-classifier
|
||||
|
||||
XPIDLSRCS = nsIUrlClassifierDBService.idl \
|
||||
nsIUrlClassifierStreamUpdater.idl \
|
||||
nsIUrlClassifierTable.idl \
|
||||
nsIUrlListManager.idl \
|
||||
$(NULL)
|
||||
|
@ -49,7 +49,7 @@ interface nsIUrlClassifierCallback : nsISupports {
|
||||
* It provides async methods for querying and updating the database. As the
|
||||
* methods complete, they call the callback function.
|
||||
*/
|
||||
[scriptable, uuid(88519724-2225-4b4f-8ba7-365b4d138c3a)]
|
||||
[scriptable, uuid(61759a52-fbbb-4c5e-b1df-fce67b6d10c8)]
|
||||
interface nsIUrlClassifierDBService : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -67,6 +67,30 @@ interface nsIUrlClassifierDBService : nsISupports
|
||||
* allows us to keep track of the table version in our main thread.
|
||||
*/
|
||||
void updateTables(in ACString updateString, in nsIUrlClassifierCallback c);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Incremental update methods. These are named to match similar methods
|
||||
// in, e.g., nsICryptoHash.
|
||||
|
||||
/**
|
||||
* Update the table incrementally.
|
||||
*/
|
||||
void update(in ACString updateChunk);
|
||||
|
||||
// It would be nice to have an updateFromStream method to round out the
|
||||
// interface, but it's tricky because of XPCOM proxies.
|
||||
|
||||
/**
|
||||
* Finish an incremental update. This commits any pending tables and
|
||||
* calls the callback for each completed table.
|
||||
*/
|
||||
void finish(in nsIUrlClassifierCallback c);
|
||||
|
||||
/**
|
||||
* Cancel an incremental update. This rolls back and pending changes.
|
||||
* and resets the stream interface.
|
||||
*/
|
||||
void cancelStream();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,59 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** 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> (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 ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIUrlClassifierDBService.idl"
|
||||
|
||||
/**
|
||||
* This is a class to help with the
|
||||
*/
|
||||
[scriptable, uuid(45b57a99-0c1a-4096-9d16-c4766d75fbea)]
|
||||
interface nsIUrlClassifierStreamUpdater : nsISupports
|
||||
{
|
||||
/**
|
||||
* The Url to download from. Should be plain ascii text.
|
||||
*/
|
||||
attribute ACString updateUrl;
|
||||
|
||||
/**
|
||||
* Try to download updates from updateUrl. Only one instance of this
|
||||
* runs at a time, so we return false if another instance is already
|
||||
* running.
|
||||
*/
|
||||
boolean downloadUpdates(in nsIUrlClassifierCallback c);
|
||||
};
|
@ -12,14 +12,15 @@
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
* The Original Code is Url Classifier code
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* 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> (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
|
||||
|
@ -12,13 +12,15 @@ MOZILLA_INTERNAL_API = 1
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
|
||||
REQUIRES = storage \
|
||||
REQUIRES = necko \
|
||||
storage \
|
||||
string \
|
||||
xpcom \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
nsUrlClassifierDBService.cpp \
|
||||
nsUrlClassifierStreamUpdater.cpp \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
|
@ -51,11 +51,12 @@
|
||||
#include "nsIProxyObjectManager.h"
|
||||
#include "nsToolkitCompsCID.h"
|
||||
#include "nsUrlClassifierDBService.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "prlog.h"
|
||||
#include "prmon.h"
|
||||
|
||||
// NSPR_LOG_MODULES=UrlClassifierDbService:5
|
||||
#if defined(PR_LOGGING)
|
||||
static const PRLogModuleInfo *gUrlClassifierDbServiceLog = nsnull;
|
||||
#define LOG(args) PR_LOG(gUrlClassifierDbServiceLog, PR_LOG_DEBUG, args)
|
||||
@ -149,13 +150,25 @@ private:
|
||||
// to be created in the background thread (currently mozStorageConnection
|
||||
// isn't thread safe).
|
||||
mozIStorageConnection* mConnection;
|
||||
|
||||
// True if we're in the middle of a streaming update.
|
||||
PRBool mHasPendingUpdate;
|
||||
|
||||
// For incremental updates, keep track of tables that have been updated.
|
||||
// When finish() is called, we go ahead and pass these update lines to
|
||||
// the callback.
|
||||
nsTArray<nsCString> mTableUpdateLines;
|
||||
|
||||
// We receive data in small chunks that may be broken in the middle of
|
||||
// a line. So we save the last partial line here.
|
||||
nsCString mPendingStreamUpdate;
|
||||
};
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsUrlClassifierDBServiceWorker,
|
||||
nsIUrlClassifierDBServiceWorker)
|
||||
|
||||
nsUrlClassifierDBServiceWorker::nsUrlClassifierDBServiceWorker()
|
||||
: mConnection(nsnull)
|
||||
: mConnection(nsnull), mHasPendingUpdate(PR_FALSE), mTableUpdateLines()
|
||||
{
|
||||
}
|
||||
nsUrlClassifierDBServiceWorker::~nsUrlClassifierDBServiceWorker()
|
||||
@ -170,7 +183,8 @@ nsUrlClassifierDBServiceWorker::~nsUrlClassifierDBServiceWorker()
|
||||
NS_IMETHODIMP
|
||||
nsUrlClassifierDBServiceWorker::Exists(const nsACString& tableName,
|
||||
const nsACString& key,
|
||||
nsIUrlClassifierCallback *c) {
|
||||
nsIUrlClassifierCallback *c)
|
||||
{
|
||||
LOG(("Exists\n"));
|
||||
|
||||
nsresult rv = OpenDb();
|
||||
@ -214,7 +228,8 @@ nsUrlClassifierDBServiceWorker::Exists(const nsACString& tableName,
|
||||
// we call the callback with the table line.
|
||||
NS_IMETHODIMP
|
||||
nsUrlClassifierDBServiceWorker::UpdateTables(const nsACString& updateString,
|
||||
nsIUrlClassifierCallback *c) {
|
||||
nsIUrlClassifierCallback *c)
|
||||
{
|
||||
LOG(("Updating tables\n"));
|
||||
|
||||
nsresult rv = OpenDb();
|
||||
@ -251,11 +266,14 @@ nsUrlClassifierDBServiceWorker::UpdateTables(const nsACString& updateString,
|
||||
getter_AddRefs(deleteStatement));
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "malformed table line");
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// If it's a new table, we must have completed the last table.
|
||||
// Go ahead and post the completion to the UI thread.
|
||||
// XXX This shouldn't happen before we commit the transaction.
|
||||
if (lastTableLine.Length() > 0)
|
||||
// If it's a new table, we may have completed a table.
|
||||
// Go ahead and post the completion to the UI thread and db.
|
||||
if (lastTableLine.Length() > 0) {
|
||||
mConnection->CommitTransaction();
|
||||
c->HandleEvent(lastTableLine);
|
||||
|
||||
mConnection->BeginTransaction();
|
||||
}
|
||||
lastTableLine.Assign(line);
|
||||
}
|
||||
} else {
|
||||
@ -276,6 +294,109 @@ nsUrlClassifierDBServiceWorker::UpdateTables(const nsACString& updateString,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUrlClassifierDBServiceWorker::Update(const nsACString& chunk)
|
||||
{
|
||||
LOG(("Update from Stream."));
|
||||
nsresult rv = OpenDb();
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("Unable to open database");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCAutoString updateString(mPendingStreamUpdate);
|
||||
updateString.Append(chunk);
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> updateStatement;
|
||||
nsCOMPtr<mozIStorageStatement> deleteStatement;
|
||||
nsCAutoString dbTableName;
|
||||
|
||||
// If we're not in the middle of an update, we start a new transaction.
|
||||
// Otherwise, we need to pick up where we left off.
|
||||
if (!mHasPendingUpdate) {
|
||||
mConnection->BeginTransaction();
|
||||
mHasPendingUpdate = PR_TRUE;
|
||||
} else {
|
||||
PRUint32 numTables = mTableUpdateLines.Length();
|
||||
if (numTables > 0) {
|
||||
const nsDependentCSubstring &line = Substring(
|
||||
mTableUpdateLines[numTables - 1], 0);
|
||||
|
||||
rv = ProcessNewTable(line, &dbTableName,
|
||||
getter_AddRefs(updateStatement),
|
||||
getter_AddRefs(deleteStatement));
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "malformed table line");
|
||||
}
|
||||
}
|
||||
|
||||
PRUint32 cur = 0;
|
||||
PRInt32 next;
|
||||
while(cur < updateString.Length() &&
|
||||
(next = updateString.FindChar('\n', cur)) != kNotFound) {
|
||||
const nsDependentCSubstring &line = Substring(updateString,
|
||||
cur, next - cur);
|
||||
cur = next + 1; // prepare for next run
|
||||
|
||||
// Skip blank lines
|
||||
if (line.Length() == 0)
|
||||
continue;
|
||||
|
||||
if ('[' == line[0]) {
|
||||
rv = ProcessNewTable(line, &dbTableName,
|
||||
getter_AddRefs(updateStatement),
|
||||
getter_AddRefs(deleteStatement));
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "malformed table line");
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Add the line to our array of table lines.
|
||||
mTableUpdateLines.AppendElement(line);
|
||||
}
|
||||
} else {
|
||||
rv = ProcessUpdateTable(line, dbTableName, updateStatement,
|
||||
deleteStatement);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "malformed update line");
|
||||
}
|
||||
}
|
||||
// Save the remaining string fragment.
|
||||
mPendingStreamUpdate = Substring(updateString, cur);
|
||||
LOG(("pending stream update: %s", mPendingStreamUpdate.get()));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUrlClassifierDBServiceWorker::Finish(nsIUrlClassifierCallback *c)
|
||||
{
|
||||
if (!mHasPendingUpdate)
|
||||
return NS_OK;
|
||||
|
||||
LOG(("Finish, committing transaction"));
|
||||
mConnection->CommitTransaction();
|
||||
|
||||
for (PRUint32 i = 0; i < mTableUpdateLines.Length(); ++i) {
|
||||
c->HandleEvent(mTableUpdateLines[i]);
|
||||
}
|
||||
mTableUpdateLines.Clear();
|
||||
mPendingStreamUpdate.Truncate();
|
||||
mHasPendingUpdate = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUrlClassifierDBServiceWorker::CancelStream()
|
||||
{
|
||||
if (!mHasPendingUpdate)
|
||||
return NS_OK;
|
||||
|
||||
LOG(("CancelStream, rolling back transaction"));
|
||||
mConnection->RollbackTransaction();
|
||||
|
||||
mTableUpdateLines.Clear();
|
||||
mPendingStreamUpdate.Truncate();
|
||||
mHasPendingUpdate = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Allows the main thread to delete the connection which may be in
|
||||
// a background thread.
|
||||
// XXX This could be turned into a single shutdown event so the logic
|
||||
@ -409,7 +530,8 @@ nsUrlClassifierDBServiceWorker::OpenDb()
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsUrlClassifierDBServiceWorker::MaybeCreateTable(const nsCString& aTableName) {
|
||||
nsUrlClassifierDBServiceWorker::MaybeCreateTable(const nsCString& aTableName)
|
||||
{
|
||||
LOG(("MaybeCreateTable %s\n", aTableName.get()));
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> createStatement;
|
||||
@ -426,7 +548,8 @@ nsUrlClassifierDBServiceWorker::MaybeCreateTable(const nsCString& aTableName) {
|
||||
|
||||
void
|
||||
nsUrlClassifierDBServiceWorker::GetDbTableName(const nsACString& aTableName,
|
||||
nsCString* aDbTableName) {
|
||||
nsCString* aDbTableName)
|
||||
{
|
||||
aDbTableName->Assign(aTableName);
|
||||
aDbTableName->ReplaceChar('-', '_');
|
||||
}
|
||||
@ -568,6 +691,75 @@ nsUrlClassifierDBService::UpdateTables(const nsACString& updateString,
|
||||
return proxy->UpdateTables(updateString, proxyCallback);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUrlClassifierDBService::Update(const nsACString& aUpdateChunk)
|
||||
{
|
||||
NS_ENSURE_TRUE(gDbBackgroundThread, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// The actual worker uses the background thread.
|
||||
nsCOMPtr<nsIUrlClassifierDBServiceWorker> proxy;
|
||||
rv = NS_GetProxyForObject(gDbBackgroundThread,
|
||||
NS_GET_IID(nsIUrlClassifierDBServiceWorker),
|
||||
mWorker,
|
||||
NS_PROXY_ASYNC,
|
||||
getter_AddRefs(proxy));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return proxy->Update(aUpdateChunk);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUrlClassifierDBService::Finish(nsIUrlClassifierCallback *c)
|
||||
{
|
||||
NS_ENSURE_TRUE(gDbBackgroundThread, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsCOMPtr<nsIUrlClassifierCallback> wrapper =
|
||||
new nsUrlClassifierCallbackWrapper(c);
|
||||
NS_ENSURE_TRUE(wrapper, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsresult rv;
|
||||
// The proxy callback uses the current thread.
|
||||
nsCOMPtr<nsIUrlClassifierCallback> proxyCallback;
|
||||
rv = NS_GetProxyForObject(NS_PROXY_TO_CURRENT_THREAD,
|
||||
NS_GET_IID(nsIUrlClassifierCallback),
|
||||
wrapper,
|
||||
NS_PROXY_ASYNC,
|
||||
getter_AddRefs(proxyCallback));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// The actual worker uses the background thread.
|
||||
nsCOMPtr<nsIUrlClassifierDBServiceWorker> proxy;
|
||||
rv = NS_GetProxyForObject(gDbBackgroundThread,
|
||||
NS_GET_IID(nsIUrlClassifierDBServiceWorker),
|
||||
mWorker,
|
||||
NS_PROXY_ASYNC,
|
||||
getter_AddRefs(proxy));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return proxy->Finish(proxyCallback);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUrlClassifierDBService::CancelStream()
|
||||
{
|
||||
NS_ENSURE_TRUE(gDbBackgroundThread, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// The actual worker uses the background thread.
|
||||
nsCOMPtr<nsIUrlClassifierDBServiceWorker> proxy;
|
||||
rv = NS_GetProxyForObject(gDbBackgroundThread,
|
||||
NS_GET_IID(nsIUrlClassifierDBServiceWorker),
|
||||
mWorker,
|
||||
NS_PROXY_ASYNC,
|
||||
getter_AddRefs(proxy));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return proxy->CancelStream();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUrlClassifierDBService::Observe(nsISupports *aSubject, const char *aTopic,
|
||||
const PRUnichar *aData)
|
||||
|
@ -0,0 +1,209 @@
|
||||
//* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** 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> (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 ***** */
|
||||
|
||||
#include "nsIURI.h"
|
||||
#include "nsIUrlClassifierDBService.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsToolkitCompsCID.h"
|
||||
#include "nsUrlClassifierStreamUpdater.h"
|
||||
#include "prlog.h"
|
||||
|
||||
// NSPR_LOG_MODULES=UrlClassifierStreamUpdater:5
|
||||
#if defined(PR_LOGGING)
|
||||
static const PRLogModuleInfo *gUrlClassifierStreamUpdaterLog = nsnull;
|
||||
#define LOG(args) PR_LOG(gUrlClassifierStreamUpdaterLog, PR_LOG_DEBUG, args)
|
||||
#else
|
||||
#define LOG(args)
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Stream listener for incremental download of url tables.
|
||||
|
||||
class nsUrlClassifierStreamUpdater;
|
||||
|
||||
class TableUpdateListener : public nsIStreamListener
|
||||
{
|
||||
public:
|
||||
TableUpdateListener(nsIUrlClassifierCallback *c);
|
||||
nsCOMPtr<nsIUrlClassifierDBService> mDBService;
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
|
||||
private:
|
||||
~TableUpdateListener() {};
|
||||
|
||||
// Callback when table updates complete.
|
||||
nsCOMPtr<nsIUrlClassifierCallback> mCallback;
|
||||
};
|
||||
|
||||
TableUpdateListener::TableUpdateListener(nsIUrlClassifierCallback *c)
|
||||
{
|
||||
mCallback = c;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS2(TableUpdateListener, nsIStreamListener, nsIRequestObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
TableUpdateListener::OnStartRequest(nsIRequest *request, nsISupports* context)
|
||||
{
|
||||
nsresult rv;
|
||||
if (!mDBService) {
|
||||
mDBService = do_GetService(NS_URLCLASSIFIERDBSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TableUpdateListener::OnDataAvailable(nsIRequest *request,
|
||||
nsISupports* context,
|
||||
nsIInputStream *aIStream,
|
||||
PRUint32 aSourceOffset,
|
||||
PRUint32 aLength)
|
||||
{
|
||||
LOG(("OnDataAvailable (%d bytes)", aLength));
|
||||
|
||||
NS_ASSERTION(mDBService != nsnull, "UrlClassifierDBService is null");
|
||||
|
||||
nsresult rv;
|
||||
// Copy the data into a nsCString
|
||||
nsCString chunk;
|
||||
rv = NS_ConsumeStream(aIStream, aLength, chunk);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
LOG(("Chunk (%d): %s\n\n", chunk.Length(), chunk.get()));
|
||||
|
||||
rv = mDBService->Update(chunk);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TableUpdateListener::OnStopRequest(nsIRequest *request, nsISupports* context,
|
||||
nsresult aStatus)
|
||||
{
|
||||
LOG(("OnStopRequest status: %d", aStatus));
|
||||
|
||||
// If we got the whole stream, call Finish to commit the changes.
|
||||
// Otherwise, call Cancel to rollback the changes.
|
||||
if (NS_SUCCEEDED(aStatus))
|
||||
mDBService->Finish(mCallback);
|
||||
else
|
||||
mDBService->CancelStream();
|
||||
|
||||
nsUrlClassifierStreamUpdater* updater =
|
||||
NS_STATIC_CAST(nsUrlClassifierStreamUpdater*, context);
|
||||
NS_ASSERTION(updater != nsnull, "failed to cast context");
|
||||
updater->mIsUpdating = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// nsIUrlClassiferStreamUpdater implementation
|
||||
// Handles creating/running the stream listener
|
||||
|
||||
nsUrlClassifierStreamUpdater::nsUrlClassifierStreamUpdater()
|
||||
: mIsUpdating(PR_FALSE), mUpdateUrl(nsnull)
|
||||
{
|
||||
#if defined(PR_LOGGING)
|
||||
if (!gUrlClassifierStreamUpdaterLog)
|
||||
gUrlClassifierStreamUpdaterLog = PR_NewLogModule("UrlClassifierStreamUpdater");
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsUrlClassifierStreamUpdater, nsIUrlClassifierStreamUpdater)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUrlClassifierStreamUpdater::GetUpdateUrl(nsACString & aUpdateUrl)
|
||||
{
|
||||
if (mUpdateUrl) {
|
||||
mUpdateUrl->GetSpec(aUpdateUrl);
|
||||
} else {
|
||||
aUpdateUrl.Truncate();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUrlClassifierStreamUpdater::SetUpdateUrl(const nsACString & aUpdateUrl)
|
||||
{
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(mUpdateUrl), aUpdateUrl);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUrlClassifierStreamUpdater::DownloadUpdates(nsIUrlClassifierCallback *c,
|
||||
PRBool *_retval)
|
||||
{
|
||||
if (mIsUpdating) {
|
||||
LOG(("already updating, skipping update"));
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!mUpdateUrl) {
|
||||
NS_ERROR("updateUrl not set");
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
// Ok, try to create the download channel.
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
rv = NS_NewChannel(getter_AddRefs(channel), mUpdateUrl);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mListener) {
|
||||
mListener = new TableUpdateListener(c);
|
||||
}
|
||||
|
||||
// Make the request
|
||||
rv = channel->AsyncOpen(mListener.get(), this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mIsUpdating = PR_TRUE;
|
||||
*_retval = PR_TRUE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
//* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-/
|
||||
/* ***** 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> (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 ***** */
|
||||
|
||||
#ifndef nsUrlClassifierStreamUpdater_h_
|
||||
#define nsUrlClassifierStreamUpdater_h_
|
||||
|
||||
#include <nsISupportsUtils.h>
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIUrlClassifierStreamUpdater.h"
|
||||
#include "nsIStreamListener.h"
|
||||
|
||||
// Forward declare pointers
|
||||
class nsIURI;
|
||||
|
||||
class nsUrlClassifierStreamUpdater : public nsIUrlClassifierStreamUpdater
|
||||
{
|
||||
public:
|
||||
nsUrlClassifierStreamUpdater();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIURLCLASSIFIERSTREAMUPDATER
|
||||
|
||||
PRBool mIsUpdating;
|
||||
|
||||
private:
|
||||
// No subclassing
|
||||
~nsUrlClassifierStreamUpdater() {};
|
||||
|
||||
// Disallow copy constructor
|
||||
nsUrlClassifierStreamUpdater(nsUrlClassifierStreamUpdater&);
|
||||
|
||||
nsCOMPtr<nsIURI> mUpdateUrl;
|
||||
nsCOMPtr<nsIStreamListener> mListener;
|
||||
};
|
||||
|
||||
#endif // nsUrlClassifierStreamUpdater_h_
|
Loading…
Reference in New Issue
Block a user