Bug 553489 - Part7: SetFaviconDataStep. r=sdwilsh

This commit is contained in:
Marco Bonardo 2010-03-25 12:34:42 +01:00
Родитель 01806dfb2c
Коммит 95b485423a
4 изменённых файлов: 142 добавлений и 20 удалений

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

@ -533,9 +533,10 @@ EnsureDatabaseEntryStep::Run()
// Statement is null if we are shutting down.
FAVICONSTEP_CANCEL_IF_TRUE(!stmt, PR_FALSE);
mozStorageStatementScoper scoper(stmt);
rv = BindStatementURI(stmt, 0, mStepper->mIconURI);
rv = stmt->BindNullParameter(0);
FAVICONSTEP_FAIL_IF_FALSE(NS_SUCCEEDED(rv));
rv = BindStatementURI(stmt, 1, mStepper->mIconURI);
FAVICONSTEP_FAIL_IF_FALSE(NS_SUCCEEDED(rv));
nsCOMPtr<mozIStoragePendingStatement> ps;
rv = stmt->ExecuteAsync(this, getter_AddRefs(ps));
FAVICONSTEP_FAIL_IF_FALSE(NS_SUCCEEDED(rv));
@ -761,6 +762,104 @@ FetchNetworkIconStep::OnChannelRedirect(nsIChannel* oldChannel,
}
////////////////////////////////////////////////////////////////////////////////
//// SetFaviconDataStep
NS_IMPL_ISUPPORTS_INHERITED0(
SetFaviconDataStep
, AsyncFaviconStep
)
ASYNC_STATEMENT_HANDLEERROR_IMPL(SetFaviconDataStep)
ASYNC_STATEMENT_EMPTY_HANDLERESULT_IMPL(SetFaviconDataStep)
void
SetFaviconDataStep::Run()
{
NS_ASSERTION(mStepper, "Step is not associated to a stepper");
FAVICONSTEP_FAIL_IF_FALSE(mStepper->mIconURI);
FAVICONSTEP_FAIL_IF_FALSE(mStepper->mData.Length() > 0);
FAVICONSTEP_FAIL_IF_FALSE(!mStepper->mMimeType.IsEmpty());
nsresult rv;
if (!(mStepper->mIconStatus & ICON_STATUS_CHANGED)) {
// There is no new data to save, just proceed to next step.
rv = mStepper->Step();
FAVICONSTEP_FAIL_IF_FALSE(NS_SUCCEEDED(rv));
return;
}
nsFaviconService* fs = nsFaviconService::GetFaviconService();
FAVICONSTEP_FAIL_IF_FALSE(fs);
// Even if the page provides a large image for the favicon (eg, a highres
// image or a multiresolution .ico file), don't try to store more data than
// needed.
nsCAutoString newData, newMimeType;
if (mStepper->mData.Length() > MAX_ICON_FILESIZE(fs->GetOptimizedIconDimension())) {
rv = fs->OptimizeFaviconImage(TO_INTBUFFER(mStepper->mData),
mStepper->mData.Length(),
mStepper->mMimeType,
newData,
newMimeType);
if (NS_SUCCEEDED(rv) && newData.Length() < mStepper->mData.Length()) {
mStepper->mData = newData;
mStepper->mMimeType = newMimeType;
}
// If over the maximum size allowed, don't save data to the database to
// avoid bloating it.
FAVICONSTEP_CANCEL_IF_TRUE(mStepper->mData.Length() > MAX_FAVICON_SIZE, PR_FALSE);
}
// Save the icon data to the database.
mozIStorageStatement* stmt =
fs->GetStatementById(mozilla::places::DB_INSERT_ICON);
// Statement is null if we are shutting down.
FAVICONSTEP_CANCEL_IF_TRUE(!stmt, PR_FALSE);
mozStorageStatementScoper scoper(stmt);
if (!mStepper->mIconId) {
rv = stmt->BindNullParameter(0);
}
else {
rv = stmt->BindInt64Parameter(0, mStepper->mIconId);
}
FAVICONSTEP_FAIL_IF_FALSE(NS_SUCCEEDED(rv));
rv = BindStatementURI(stmt, 1, mStepper->mIconURI);
FAVICONSTEP_FAIL_IF_FALSE(NS_SUCCEEDED(rv));
rv = stmt->BindBlobParameter(2, TO_INTBUFFER(mStepper->mData),
mStepper->mData.Length());
FAVICONSTEP_FAIL_IF_FALSE(NS_SUCCEEDED(rv));
rv = stmt->BindUTF8StringParameter(3, mStepper->mMimeType);
FAVICONSTEP_FAIL_IF_FALSE(NS_SUCCEEDED(rv));
rv = stmt->BindInt64Parameter(4, mStepper->mExpiration);
FAVICONSTEP_FAIL_IF_FALSE(NS_SUCCEEDED(rv));
nsCOMPtr<mozIStoragePendingStatement> ps;
rv = stmt->ExecuteAsync(this, getter_AddRefs(ps));
FAVICONSTEP_FAIL_IF_FALSE(NS_SUCCEEDED(rv));
// ExecuteAsync will reset the statement for us.
scoper.Abandon();
}
NS_IMETHODIMP
SetFaviconDataStep::HandleCompletion(PRUint16 aReason)
{
FAVICONSTEP_FAIL_IF_FALSE_RV(aReason == mozIStorageStatementCallback::REASON_FINISHED, NS_OK);
mStepper->mIconStatus |= ICON_STATUS_SAVED;
// Proceed to next step.
nsresult rv = mStepper->Step();
FAVICONSTEP_FAIL_IF_FALSE_RV(NS_SUCCEEDED(rv), rv);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
} // namespace places

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

@ -348,6 +348,21 @@ private:
nsCString mData;
};
/**
* Saves icon data in the database if it has changed.
*/
class SetFaviconDataStep : public AsyncFaviconStep
, public mozilla::places::AsyncStatementCallback
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_MOZISTORAGESTATEMENTCALLBACK
SetFaviconDataStep() {};
void Run();
};
} // namespace places
} // namespace mozilla

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

@ -78,10 +78,6 @@
// Default value for mOptimizedIconDimension
#define OPTIMIZED_FAVICON_DIMENSION 16
// Most icons will be smaller than this rough estimate of the size of an
// uncompressed 16x16 RGBA image of the same dimensions.
#define MAX_ICON_FILESIZE(s) ((PRUint32) s*s*4)
#define MAX_FAVICON_CACHE_SIZE 256
#define FAVICON_CACHE_REDUCE_COUNT 64
@ -413,8 +409,8 @@ nsFaviconService::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
"SELECT f.data, f.mime_type FROM moz_favicons f WHERE url = ?1"));
RETURN_IF_STMT(mDBInsertIcon, NS_LITERAL_CSTRING(
"INSERT INTO moz_favicons (url, data, mime_type, expiration) "
"VALUES (?1, ?2, ?3, ?4)"));
"INSERT OR REPLACE INTO moz_favicons (id, url, data, mime_type, expiration) "
"VALUES (?1, ?2, ?3, ?4, ?5)"));
RETURN_IF_STMT(mDBUpdateIcon, NS_LITERAL_CSTRING(
"UPDATE moz_favicons SET data = ?2, mime_type = ?3, expiration = ?4 "
@ -581,12 +577,12 @@ nsFaviconService::SetFaviconUrlForPageInternal(nsIURI* aPageURI,
if (iconId == -1) {
// We did not find any entry, so create a new one
// not-binded params are automatically nullified by mozStorage
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(stmt, mDBInsertIcon);
rv = BindStatementURI(stmt, 0, aFaviconURI);
rv = stmt->BindNullParameter(0);
NS_ENSURE_SUCCESS(rv, rv);
rv = BindStatementURI(stmt, 1, aFaviconURI);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->Execute();
NS_ENSURE_SUCCESS(rv, rv);
@ -807,25 +803,33 @@ nsFaviconService::SetFaviconData(nsIURI* aFaviconURI, const PRUint8* aData,
statement = GetStatement(mDBUpdateIcon);
NS_ENSURE_STATE(statement);
rv = statement->BindInt64Parameter(0, id);
}
else {
// insert new one (statement parameter 0 = favicon URL)
statement = GetStatement(mDBInsertIcon);
NS_ENSURE_STATE(statement);
rv = BindStatementURI(statement, 0, aFaviconURI);
}
NS_ENSURE_SUCCESS(rv, rv);
}
mozStorageStatementScoper scoper(statement);
// the insert and update statements share all but the 0th parameter
rv = statement->BindBlobParameter(1, data, dataLen);
NS_ENSURE_SUCCESS(rv, rv);
rv = statement->BindUTF8StringParameter(2, *mimeType);
NS_ENSURE_SUCCESS(rv, rv);
rv = statement->BindInt64Parameter(3, aExpiration);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
// insert new one (statement parameter 0 = favicon URL)
statement = GetStatement(mDBInsertIcon);
NS_ENSURE_STATE(statement);
rv = statement->BindNullParameter(0);
NS_ENSURE_SUCCESS(rv, rv);
rv = BindStatementURI(statement, 1, aFaviconURI);
NS_ENSURE_SUCCESS(rv, rv);
rv = statement->BindBlobParameter(2, data, dataLen);
NS_ENSURE_SUCCESS(rv, rv);
rv = statement->BindUTF8StringParameter(3, *mimeType);
NS_ENSURE_SUCCESS(rv, rv);
rv = statement->BindInt64Parameter(4, aExpiration);
NS_ENSURE_SUCCESS(rv, rv);
}
}
mozStorageStatementScoper scoper(statement);
rv = statement->Execute();
NS_ENSURE_SUCCESS(rv, rv);

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

@ -62,6 +62,9 @@ namespace places {
} // namespace places
} // namespace mozilla
// Most icons will be smaller than this rough estimate of the size of an
// uncompressed 16x16 RGBA image of the same dimensions.
#define MAX_ICON_FILESIZE(s) ((PRUint32) s*s*4)
// forward class definitions
class mozIStorageStatementCallback;
@ -112,6 +115,7 @@ public:
nsresult OptimizeFaviconImage(const PRUint8* aData, PRUint32 aDataLen,
const nsACString& aMimeType,
nsACString& aNewData, nsACString& aNewMimeType);
PRInt32 GetOptimizedIconDimension() { return mOptimizedIconDimension; }
/**
* Obtains the favicon data asynchronously.