Bug 1261386 - Avoid history flooding from repeated reloads. r=adw

MozReview-Commit-ID: FhU8nOoNUHb
This commit is contained in:
Marco Bonardo
2016-05-26 17:49:40 +02:00
parent 4fa7b5805a
commit c1bfd3aba5
19 changed files with 215 additions and 186 deletions

View File

@@ -476,16 +476,22 @@ namespace places {
uint32_t numEntries;
nsresult rv = aArguments->GetNumEntries(&numEntries);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(numEntries > 0, "unexpected number of arguments");
MOZ_ASSERT(numEntries == 1, "unexpected number of arguments");
int64_t pageId = aArguments->AsInt64(0);
int32_t typed = numEntries > 1 ? aArguments->AsInt32(1) : 0;
int32_t fullVisitCount = numEntries > 2 ? aArguments->AsInt32(2) : 0;
int64_t bookmarkId = numEntries > 3 ? aArguments->AsInt64(3) : 0;
MOZ_ASSERT(pageId > 0, "Should always pass a valid page id");
if (pageId <= 0) {
NS_ADDREF(*_result = new IntegerVariant(0));
return NS_OK;
}
int32_t typed = 0;
int32_t visitCount = 0;
int32_t hidden = 0;
bool hasBookmark = false;
int32_t isQuery = 0;
float pointsForSampledVisits = 0.0;
int32_t numSampledVisits = 0;
int32_t bonus = 0;
// This is a const version of the history object for thread-safety.
const nsNavHistory* history = nsNavHistory::GetConstHistoryService();
@@ -493,14 +499,12 @@ namespace places {
RefPtr<Database> DB = Database::GetDatabase();
NS_ENSURE_STATE(DB);
if (pageId > 0) {
// The page is already in the database, and we can fetch current
// params from the database.
// Fetch the page stats from the database.
{
RefPtr<mozIStorageStatement> getPageInfo = DB->GetStatement(
"SELECT typed, hidden, visit_count, "
"(SELECT count(*) FROM moz_historyvisits WHERE place_id = :page_id), "
"EXISTS (SELECT 1 FROM moz_bookmarks WHERE fk = :page_id), "
"(url > 'place:' AND url < 'place;') "
"SELECT typed, visit_count, foreign_count, "
"(substr(url, 0, 7) = 'place:') "
"FROM moz_places "
"WHERE id = :page_id "
);
@@ -510,29 +514,26 @@ namespace places {
rv = getPageInfo->BindInt64ByName(NS_LITERAL_CSTRING("page_id"), pageId);
NS_ENSURE_SUCCESS(rv, rv);
bool hasResult;
bool hasResult = false;
rv = getPageInfo->ExecuteStep(&hasResult);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(hasResult, NS_ERROR_UNEXPECTED);
NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && hasResult, NS_ERROR_UNEXPECTED);
rv = getPageInfo->GetInt32(0, &typed);
NS_ENSURE_SUCCESS(rv, rv);
rv = getPageInfo->GetInt32(1, &hidden);
rv = getPageInfo->GetInt32(1, &visitCount);
NS_ENSURE_SUCCESS(rv, rv);
rv = getPageInfo->GetInt32(2, &visitCount);
int32_t foreignCount = 0;
rv = getPageInfo->GetInt32(2, &foreignCount);
NS_ENSURE_SUCCESS(rv, rv);
rv = getPageInfo->GetInt32(3, &fullVisitCount);
NS_ENSURE_SUCCESS(rv, rv);
rv = getPageInfo->GetInt64(4, &bookmarkId);
NS_ENSURE_SUCCESS(rv, rv);
rv = getPageInfo->GetInt32(5, &isQuery);
hasBookmark = foreignCount > 0;
rv = getPageInfo->GetInt32(3, &isQuery);
NS_ENSURE_SUCCESS(rv, rv);
}
// NOTE: This is not limited to visits with "visit_type NOT IN (0,4,7,8)"
// because otherwise it would not return any visit for those transitions
// causing an incorrect frecency, see CalculateFrecencyInternal().
if (visitCount > 0) {
// Get a sample of the last visits to the page, to calculate its weight.
// In case of a temporary or permanent redirect, calculate the frecency
// as if the original page was visited.
// Get a sample of the last visits to the page, to calculate its weight.
nsCOMPtr<mozIStorageStatement> getVisits = DB->GetStatement(
NS_LITERAL_CSTRING(
"/* do not warn (bug 659740 - SQLite may ignore index if few visits exist) */"
@@ -551,12 +552,11 @@ namespace places {
);
NS_ENSURE_STATE(getVisits);
mozStorageStatementScoper visitsScoper(getVisits);
rv = getVisits->BindInt64ByName(NS_LITERAL_CSTRING("page_id"), pageId);
NS_ENSURE_SUCCESS(rv, rv);
// Fetch only a limited number of recent visits.
int32_t numSampledVisits = 0;
bool hasResult = false;
for (int32_t maxVisits = history->GetNumVisitsForFrecency();
numSampledVisits < maxVisits &&
NS_SUCCEEDED(getVisits->ExecuteStep(&hasResult)) && hasResult;
@@ -564,10 +564,10 @@ namespace places {
int32_t visitType;
rv = getVisits->GetInt32(1, &visitType);
NS_ENSURE_SUCCESS(rv, rv);
int32_t bonus = history->GetFrecencyTransitionBonus(visitType, true);
bonus = history->GetFrecencyTransitionBonus(visitType, true);
// Always add the bookmark visit bonus.
if (bookmarkId) {
// Add the bookmark visit bonus.
if (hasBookmark) {
bonus += history->GetFrecencyTransitionBonus(nsINavHistoryService::TRANSITION_BOOKMARK, true);
}
@@ -578,56 +578,49 @@ namespace places {
pointsForSampledVisits += (float)(weight * (bonus / 100.0));
}
}
// If we found some visits for this page, use the calculated weight.
if (numSampledVisits) {
// fix for bug #412219
if (!pointsForSampledVisits) {
// For URIs with zero points in the sampled recent visits
// but "browsing" type visits outside the sampling range, set
// frecency to -visit_count, so they're still shown in autocomplete.
NS_ADDREF(*_result = new IntegerVariant(-visitCount));
}
else {
// Estimate frecency using the last few visits.
// Use ceilf() so that we don't round down to 0, which
// would cause us to completely ignore the place during autocomplete.
NS_ADDREF(*_result = new IntegerVariant((int32_t) ceilf(fullVisitCount * ceilf(pointsForSampledVisits) / numSampledVisits)));
}
return NS_OK;
}
}
// This page is unknown or has no visits. It could have just been added, so
// use passed in or default values.
// If we sampled some visits for this page, use the calculated weight.
if (numSampledVisits) {
// We were unable to calculate points, maybe cause all the visits in the
// sample had a zero bonus. Though, we know the page has some past valid
// visit, or visit_count would be zero. Thus we set the frecency to
// -1, so they are still shown in autocomplete.
if (!pointsForSampledVisits) {
NS_ADDREF(*_result = new IntegerVariant(-1));
}
else {
// Estimate frecency using the sampled visits.
// Use ceilf() so that we don't round down to 0, which
// would cause us to completely ignore the place during autocomplete.
NS_ADDREF(*_result = new IntegerVariant((int32_t) ceilf(visitCount * ceilf(pointsForSampledVisits) / numSampledVisits)));
}
return NS_OK;
}
// The code below works well for guessing the frecency on import, and we'll
// correct later once we have visits.
// TODO: What if we don't have visits and we never visit? We could end up
// with a really high value that keeps coming up in ac results? Should we
// only do this on import? Have to figure it out.
int32_t bonus = 0;
// Otherwise this page has no visits, it may be bookmarked.
if (!hasBookmark || isQuery) {
NS_ADDREF(*_result = new IntegerVariant(0));
return NS_OK;
}
// For unvisited bookmarks, produce a non-zero frecency, so that they show
// up in URL bar autocomplete.
visitCount = 1;
// Make it so something bookmarked and typed will have a higher frecency
// than something just typed or just bookmarked.
if (bookmarkId && !isQuery) {
bonus += history->GetFrecencyTransitionBonus(nsINavHistoryService::TRANSITION_BOOKMARK, false);;
// For unvisited bookmarks, produce a non-zero frecency, so that they show
// up in URL bar autocomplete.
fullVisitCount = 1;
}
bonus += history->GetFrecencyTransitionBonus(nsINavHistoryService::TRANSITION_BOOKMARK, false);
if (typed) {
bonus += history->GetFrecencyTransitionBonus(nsINavHistoryService::TRANSITION_TYPED, false);
}
// Assume "now" as our ageInDays, so use the first bucket.
pointsForSampledVisits = history->GetFrecencyBucketWeight(1) * (bonus / (float)100.0);
pointsForSampledVisits = history->GetFrecencyBucketWeight(1) * (bonus / (float)100.0);
// use ceilf() so that we don't round down to 0, which
// would cause us to completely ignore the place during autocomplete
NS_ADDREF(*_result = new IntegerVariant((int32_t) ceilf(fullVisitCount * ceilf(pointsForSampledVisits))));
NS_ADDREF(*_result = new IntegerVariant((int32_t) ceilf(visitCount * ceilf(pointsForSampledVisits))));
return NS_OK;
}