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

MozReview-Commit-ID: FhU8nOoNUHb

--HG--
extra : rebase_source : ff75adb252b13f4042da49d4572fb807c3d0d823
This commit is contained in:
Marco Bonardo 2016-05-26 17:49:40 +02:00
parent 84a96ef029
commit 392c65b534
19 changed files with 215 additions and 186 deletions

View File

@ -836,6 +836,7 @@ pref("places.frecency.bookmarkVisitBonus", 75);
pref("places.frecency.downloadVisitBonus", 0);
pref("places.frecency.permRedirectVisitBonus", 0);
pref("places.frecency.tempRedirectVisitBonus", 0);
pref("places.frecency.reloadVisitBonus", 0);
pref("places.frecency.defaultVisitBonus", 0);
// bonus (in percent) for place types for frecency calculations

View File

@ -302,8 +302,8 @@ HistoryStore.prototype = {
continue;
}
if (!visit.type || !(visit.type >= PlacesUtils.history.TRANSITION_LINK &&
visit.type <= PlacesUtils.history.TRANSITION_FRAMED_LINK)) {
if (!visit.type ||
!Object.values(PlacesUtils.history.TRANSITIONS).includes(visit.type)) {
this._log.warn("Encountered record with invalid visit type: " +
visit.type + "; ignoring.");
continue;

View File

@ -1210,8 +1210,8 @@ private:
_place.visitTime);
NS_ENSURE_SUCCESS(rv, rv);
uint32_t transitionType = _place.transitionType;
NS_ASSERTION(transitionType >= nsINavHistoryService::TRANSITION_LINK &&
transitionType <= nsINavHistoryService::TRANSITION_FRAMED_LINK,
MOZ_ASSERT(transitionType >= nsINavHistoryService::TRANSITION_LINK &&
transitionType <= nsINavHistoryService::TRANSITION_RELOAD,
"Invalid transition type!");
rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("visit_type"),
transitionType);
@ -1970,7 +1970,7 @@ History::History()
: mShuttingDown(false)
, mShutdownMutex("History::mShutdownMutex")
, mObservers(VISIT_OBSERVERS_INITIAL_CACHE_LENGTH)
, mRecentlyVisitedURIsNextIndex(0)
, mRecentlyVisitedURIs(RECENTLY_VISITED_URIS_SIZE)
{
NS_ASSERTION(!gService, "Ruh-roh! This service has already been created!");
gService = this;
@ -2406,25 +2406,29 @@ History::Shutdown()
void
History::AppendToRecentlyVisitedURIs(nsIURI* aURI) {
if (mRecentlyVisitedURIs.Length() < RECENTLY_VISITED_URI_SIZE) {
// Append a new element while the array is not full.
mRecentlyVisitedURIs.AppendElement(aURI);
} else {
// Otherwise, replace the oldest member.
mRecentlyVisitedURIsNextIndex %= RECENTLY_VISITED_URI_SIZE;
mRecentlyVisitedURIs.ElementAt(mRecentlyVisitedURIsNextIndex) = aURI;
mRecentlyVisitedURIsNextIndex++;
// Add a new entry, if necessary.
RecentURIKey* entry = mRecentlyVisitedURIs.GetEntry(aURI);
if (!entry) {
entry = mRecentlyVisitedURIs.PutEntry(aURI);
}
if (entry) {
entry->time = PR_Now();
}
// Remove entries older than RECENTLY_VISITED_URIS_MAX_AGE.
for (auto iter = mRecentlyVisitedURIs.Iter(); !iter.Done(); iter.Next()) {
RecentURIKey* entry = iter.Get();
if ((PR_Now() - entry->time) > RECENTLY_VISITED_URIS_MAX_AGE) {
iter.Remove();
}
}
}
inline bool
History::IsRecentlyVisitedURI(nsIURI* aURI) {
bool equals = false;
RecentlyVisitedArray::index_type i;
for (i = 0; i < mRecentlyVisitedURIs.Length() && !equals; ++i) {
aURI->Equals(mRecentlyVisitedURIs.ElementAt(i), &equals);
}
return equals;
RecentURIKey* entry = mRecentlyVisitedURIs.GetEntry(aURI);
// Check if the entry exists and is younger than RECENTLY_VISITED_URIS_MAX_AGE.
return entry && (PR_Now() - entry->time) < RECENTLY_VISITED_URIS_MAX_AGE;
}
////////////////////////////////////////////////////////////////////////////////
@ -2466,12 +2470,14 @@ History::VisitURI(nsIURI* aURI,
return NS_OK;
}
// Do not save a reloaded uri if we have visited the same URI recently.
bool reload = false;
if (aLastVisitedURI) {
bool same;
rv = aURI->Equals(aLastVisitedURI, &same);
rv = aURI->Equals(aLastVisitedURI, &reload);
NS_ENSURE_SUCCESS(rv, rv);
if (same && IsRecentlyVisitedURI(aURI)) {
// Do not save refresh visits if we have visited this URI recently.
if (reload && IsRecentlyVisitedURI(aURI)) {
// Regardless we must update the stored visit time.
AppendToRecentlyVisitedURIs(aURI);
return NS_OK;
}
}
@ -2507,6 +2513,9 @@ History::VisitURI(nsIURI* aURI,
else if (aFlags & IHistory::REDIRECT_PERMANENT) {
transitionType = nsINavHistoryService::TRANSITION_REDIRECT_PERMANENT;
}
else if (reload) {
transitionType = nsINavHistoryService::TRANSITION_RELOAD;
}
else if ((recentFlags & nsNavHistory::RECENT_TYPED) &&
!(aFlags & IHistory::UNRECOVERABLE_ERROR)) {
// Don't mark error pages as typed, even if they were actually typed by
@ -2948,7 +2957,7 @@ History::UpdatePlaces(JS::Handle<JS::Value> aPlaceInfos,
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_ARG_RANGE(transitionType,
nsINavHistoryService::TRANSITION_LINK,
nsINavHistoryService::TRANSITION_FRAMED_LINK);
nsINavHistoryService::TRANSITION_RELOAD);
data.SetTransitionType(transitionType);
data.hidden = GetHiddenState(false, transitionType);

View File

@ -33,8 +33,14 @@ class ConcurrentStatementsHolder;
#define NS_HISTORYSERVICE_CID \
{0x0937a705, 0x91a6, 0x417a, {0x82, 0x92, 0xb2, 0x2e, 0xb1, 0x0d, 0xa8, 0x6c}}
// Max size of History::mRecentlyVisitedURIs
#define RECENTLY_VISITED_URI_SIZE 8
// Initial size of mRecentlyVisitedURIs.
#define RECENTLY_VISITED_URIS_SIZE 64
// Microseconds after which a visit can be expired from mRecentlyVisitedURIs.
// When an URI is reloaded we only take into account the first visit to it, and
// ignore any subsequent visits, if they happen before this time has elapsed.
// A commonly found case is to reload a page every 5 minutes, so we pick a time
// larger than that.
#define RECENTLY_VISITED_URIS_MAX_AGE 6 * 60 * PR_USEC_PER_SEC
class History final : public IHistory
, public nsIDownloadHistory
@ -189,14 +195,26 @@ private:
nsTHashtable<KeyClass> mObservers;
/**
* mRecentlyVisitedURIs remembers URIs which are recently added to the DB,
* to avoid saving these locations repeatedly in a short period.
* mRecentlyVisitedURIs remembers URIs which have been recently added to
* history, to avoid saving these locations repeatedly in a short period.
*/
class RecentURIKey : public nsURIHashKey
{
public:
explicit RecentURIKey(const nsIURI* aURI) : nsURIHashKey(aURI)
{
}
RecentURIKey(const RecentURIKey& aOther) : nsURIHashKey(aOther)
{
NS_NOTREACHED("Do not call me!");
}
PRTime time;
};
nsTHashtable<RecentURIKey> mRecentlyVisitedURIs;
/**
* Whether aURI has been visited "recently".
* See RECENTLY_VISITED_URIS_MAX_AGE.
*/
typedef AutoTArray<nsCOMPtr<nsIURI>, RECENTLY_VISITED_URI_SIZE>
RecentlyVisitedArray;
RecentlyVisitedArray mRecentlyVisitedURIs;
RecentlyVisitedArray::index_type mRecentlyVisitedURIsNextIndex;
bool IsRecentlyVisitedURI(nsIURI* aURI);
};

View File

@ -40,7 +40,7 @@
* - date: (Date)
* The time the visit occurred.
* - transition: (number)
* How the user reached the page. See constants `TRANSITION_*`
* How the user reached the page. See constants `TRANSITIONS.*`
* for the possible transition types.
* - referrer: (URL)
* or (nsIURI)
@ -408,51 +408,58 @@ this.History = Object.freeze({
* objects.
*/
/**
* The user followed a link and got a new toplevel window.
*/
TRANSITION_LINK: Ci.nsINavHistoryService.TRANSITION_LINK,
TRANSITIONS: {
/**
* The user followed a link and got a new toplevel window.
*/
LINK: Ci.nsINavHistoryService.TRANSITION_LINK,
/**
* The user typed the page's URL in the URL bar or selected it from
* URL bar autocomplete results, clicked on it from a history query
* (from the History sidebar, History menu, or history query in the
* personal toolbar or Places organizer.
*/
TRANSITION_TYPED: Ci.nsINavHistoryService.TRANSITION_TYPED,
/**
* The user typed the page's URL in the URL bar or selected it from
* URL bar autocomplete results, clicked on it from a history query
* (from the History sidebar, History menu, or history query in the
* personal toolbar or Places organizer.
*/
TYPED: Ci.nsINavHistoryService.TRANSITION_TYPED,
/**
* The user followed a bookmark to get to the page.
*/
TRANSITION_BOOKMARK: Ci.nsINavHistoryService.TRANSITION_BOOKMARK,
/**
* The user followed a bookmark to get to the page.
*/
BOOKMARK: Ci.nsINavHistoryService.TRANSITION_BOOKMARK,
/**
* Some inner content is loaded. This is true of all images on a
* page, and the contents of the iframe. It is also true of any
* content in a frame if the user did not explicitly follow a link
* to get there.
*/
TRANSITION_EMBED: Ci.nsINavHistoryService.TRANSITION_EMBED,
/**
* Some inner content is loaded. This is true of all images on a
* page, and the contents of the iframe. It is also true of any
* content in a frame if the user did not explicitly follow a link
* to get there.
*/
EMBED: Ci.nsINavHistoryService.TRANSITION_EMBED,
/**
* Set when the transition was a permanent redirect.
*/
TRANSITION_REDIRECT_PERMANENT: Ci.nsINavHistoryService.TRANSITION_REDIRECT_PERMANENT,
/**
* Set when the transition was a permanent redirect.
*/
REDIRECT_PERMANENT: Ci.nsINavHistoryService.TRANSITION_REDIRECT_PERMANENT,
/**
* Set when the transition was a temporary redirect.
*/
TRANSITION_REDIRECT_TEMPORARY: Ci.nsINavHistoryService.TRANSITION_REDIRECT_TEMPORARY,
/**
* Set when the transition was a temporary redirect.
*/
REDIRECT_TEMPORARY: Ci.nsINavHistoryService.TRANSITION_REDIRECT_TEMPORARY,
/**
* Set when the transition is a download.
*/
TRANSITION_DOWNLOAD: Ci.nsINavHistoryService.TRANSITION_REDIRECT_DOWNLOAD,
/**
* Set when the transition is a download.
*/
DOWNLOAD: Ci.nsINavHistoryService.TRANSITION_DOWNLOAD,
/**
* The user followed a link and got a visit in a frame.
*/
TRANSITION_FRAMED_LINK: Ci.nsINavHistoryService.TRANSITION_FRAMED_LINK,
/**
* The user followed a link and got a visit in a frame.
*/
FRAMED_LINK: Ci.nsINavHistoryService.TRANSITION_FRAMED_LINK,
/**
* The user reloaded a page.
*/
RELOAD: Ci.nsINavHistoryService.TRANSITION_RELOAD,
},
});
/**
@ -484,7 +491,7 @@ function validatePageInfo(pageInfo) {
for (let inVisit of pageInfo.visits) {
let visit = {
date: new Date(),
transition: inVisit.transition || History.TRANSITION_LINK,
transition: inVisit.transition || History.TRANSITIONS.LINK,
};
if (!isValidTransitionType(visit.transition)) {
@ -541,16 +548,7 @@ function convertForUpdatePlaces(pageInfo) {
* @return (Boolean)
*/
function isValidTransitionType(transitionType) {
return [
History.TRANSITION_LINK,
History.TRANSITION_TYPED,
History.TRANSITION_BOOKMARK,
History.TRANSITION_EMBED,
History.TRANSITION_REDIRECT_PERMANENT,
History.TRANSITION_REDIRECT_TEMPORARY,
History.TRANSITION_DOWNLOAD,
History.TRANSITION_FRAMED_LINK
].includes(transitionType);
return Object.values(History.TRANSITIONS).includes(transitionType);
}
/**

View File

@ -690,13 +690,13 @@ this.PlacesDBUtils = {
let fixVisitStats = DBConn.createAsyncStatement(
`UPDATE moz_places
SET visit_count = (SELECT count(*) FROM moz_historyvisits
WHERE place_id = moz_places.id AND visit_type NOT IN (0,4,7,8)),
WHERE place_id = moz_places.id AND visit_type NOT IN (0,4,7,8,9)),
last_visit_date = (SELECT MAX(visit_date) FROM moz_historyvisits
WHERE place_id = moz_places.id)
WHERE id IN (
SELECT h.id FROM moz_places h
WHERE visit_count <> (SELECT count(*) FROM moz_historyvisits v
WHERE v.place_id = h.id AND visit_type NOT IN (0,4,7,8))
WHERE v.place_id = h.id AND visit_type NOT IN (0,4,7,8,9))
OR last_visit_date <> (SELECT MAX(visit_date) FROM moz_historyvisits v
WHERE v.place_id = h.id)
)`);

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

View File

@ -1257,6 +1257,11 @@ interface nsINavHistoryService : nsISupports
*/
const unsigned long TRANSITION_FRAMED_LINK = 8;
/**
* This transition type means the page has been reloaded.
*/
const unsigned long TRANSITION_RELOAD = 9;
/**
* Set when database is coherent
*/

View File

@ -99,6 +99,8 @@ using namespace mozilla::places;
#define PREF_FREC_UNVISITED_BOOKMARK_BONUS_DEF 140
#define PREF_FREC_UNVISITED_TYPED_BONUS "places.frecency.unvisitedTypedBonus"
#define PREF_FREC_UNVISITED_TYPED_BONUS_DEF 200
#define PREF_FREC_RELOAD_VISIT_BONUS "places.frecency.reloadVisitBonus"
#define PREF_FREC_RELOAD_VISIT_BONUS_DEF 0
// In order to avoid calling PR_now() too often we use a cached "now" value
// for repeating stuff. These are milliseconds between "now" cache refreshes.
@ -482,6 +484,7 @@ nsNavHistory::LoadPrefs()
FRECENCY_PREF(mDefaultVisitBonus, PREF_FREC_DEFAULT_VISIT_BONUS);
FRECENCY_PREF(mUnvisitedBookmarkBonus, PREF_FREC_UNVISITED_BOOKMARK_BONUS);
FRECENCY_PREF(mUnvisitedTypedBonus, PREF_FREC_UNVISITED_TYPED_BONUS);
FRECENCY_PREF(mReloadVisitBonus, PREF_FREC_RELOAD_VISIT_BONUS);
FRECENCY_PREF(mFirstBucketWeight, PREF_FREC_FIRST_BUCKET_WEIGHT);
FRECENCY_PREF(mSecondBucketWeight, PREF_FREC_SECOND_BUCKET_WEIGHT);
FRECENCY_PREF(mThirdBucketWeight, PREF_FREC_THIRD_BUCKET_WEIGHT);

View File

@ -412,6 +412,8 @@ public:
return mPermRedirectVisitBonus;
case nsINavHistoryService::TRANSITION_REDIRECT_TEMPORARY:
return mTempRedirectVisitBonus;
case nsINavHistoryService::TRANSITION_RELOAD:
return mReloadVisitBonus;
default:
// 0 == undefined (see bug #375777 for details)
NS_WARN_IF_FALSE(!aTransitionType, "new transition but no bonus for frecency");
@ -485,9 +487,6 @@ protected:
*/
nsresult DecayFrecency();
nsresult CalculateFrecency(int64_t aPageID, int32_t aTyped, int32_t aVisitCount, nsAutoCString &aURL, int32_t *aFrecency);
nsresult CalculateFrecencyInternal(int64_t aPageID, int32_t aTyped, int32_t aVisitCount, bool aIsBookmarked, int32_t *aFrecency);
nsresult RemovePagesInternal(const nsCString& aPlaceIdsQueryString);
nsresult CleanupPlacesOnVisitsDelete(const nsCString& aPlaceIdsQueryString);
@ -610,6 +609,7 @@ protected:
int32_t mDefaultVisitBonus;
int32_t mUnvisitedBookmarkBonus;
int32_t mUnvisitedTypedBonus;
int32_t mReloadVisitBonus;
// in nsNavHistoryQuery.cpp
nsresult TokensToQueries(const nsTArray<QueryKeyValuePair>& aTokens,

View File

@ -14,9 +14,10 @@
* 0 - invalid
* 4 - EMBED
* 7 - DOWNLOAD
* 7 - FRAMED_LINK
* 8 - FRAMED_LINK
* 9 - RELOAD
**/
#define EXCLUDED_VISIT_TYPES "0, 4, 7, 8"
#define EXCLUDED_VISIT_TYPES "0, 4, 7, 8, 9"
/**
* This triggers update visit_count and last_visit_date based on historyvisits

View File

@ -18,6 +18,7 @@ const TRANSITION_FRAMED_LINK = Ci.nsINavHistoryService.TRANSITION_FRAMED_LINK;
const TRANSITION_REDIRECT_PERMANENT = Ci.nsINavHistoryService.TRANSITION_REDIRECT_PERMANENT;
const TRANSITION_REDIRECT_TEMPORARY = Ci.nsINavHistoryService.TRANSITION_REDIRECT_TEMPORARY;
const TRANSITION_DOWNLOAD = Ci.nsINavHistoryService.TRANSITION_DOWNLOAD;
const TRANSITION_RELOAD = Ci.nsINavHistoryService.TRANSITION_RELOAD;
const TITLE_LENGTH_MAX = 4096;

View File

@ -43,6 +43,7 @@ var bonusPrefs = {
downloadVisitBonus: Ci.nsINavHistoryService.TRANSITION_DOWNLOAD,
permRedirectVisitBonus: Ci.nsINavHistoryService.TRANSITION_REDIRECT_PERMANENT,
tempRedirectVisitBonus: Ci.nsINavHistoryService.TRANSITION_REDIRECT_TEMPORARY,
reloadVisitBonus: Ci.nsINavHistoryService.TRANSITION_RELOAD,
};
// create test data
@ -110,6 +111,7 @@ function* task_initializeBucket(bucket) {
if (visitType == Ci.nsINavHistoryService.TRANSITION_EMBED ||
visitType == Ci.nsINavHistoryService.TRANSITION_FRAMED_LINK ||
visitType == Ci.nsINavHistoryService.TRANSITION_DOWNLOAD ||
visitType == Ci.nsINavHistoryService.TRANSITION_RELOAD ||
bonusName == "defaultVisitBonus")
frecency = 0;
else

View File

@ -19,7 +19,8 @@ add_task(function* test_execute()
let notcount_visited_URIs = ["http://www.test-embed.com/",
"http://www.test-download.com/",
"http://www.test-framed.com/"];
"http://www.test-framed.com/",
"http://www.test-reload.com/"];
// add visits, one for each transition type
yield PlacesTestUtils.addVisits([
@ -39,6 +40,8 @@ add_task(function* test_execute()
transition: TRANSITION_REDIRECT_TEMPORARY },
{ uri: uri("http://www.test-download.com/"),
transition: TRANSITION_DOWNLOAD },
{ uri: uri("http://www.test-reload.com/"),
transition: TRANSITION_RELOAD },
]);
// check that all links are marked as visited

View File

@ -35,7 +35,8 @@ function* task_add_visit(aURI, aVisitType)
if (aVisitType != 0 &&
aVisitType != TRANSITION_EMBED &&
aVisitType != TRANSITION_FRAMED_LINK &&
aVisitType != TRANSITION_DOWNLOAD) {
aVisitType != TRANSITION_DOWNLOAD &&
aVisitType != TRANSITION_RELOAD) {
visit_count ++;
}
@ -107,6 +108,14 @@ add_task(function* test_execute()
do_check_eq((yield task_add_visit(TEST_URI, TRANSITION_TYPED)), placeId);
check_results(1, 1);
// Add a visit that should not increase visit_count
do_check_eq((yield task_add_visit(TEST_URI, TRANSITION_RELOAD)), placeId);
check_results(1, 1);
// Add a visit that should not increase visit_count
do_check_eq((yield task_add_visit(TEST_URI, TRANSITION_DOWNLOAD)), placeId);
check_results(1, 1);
// Add a visit, check that hidden is not overwritten
// - We expect that the place has still hidden = 0, while retaining
// correct visit_count.

View File

@ -333,7 +333,7 @@ add_task(function* test_add_visit_invalid_transitionType_throws() {
}
// Now, test something that has a transition type greater than the last one.
place.visits[0] = new VisitInfo(TRANSITION_FRAMED_LINK + 1);
place.visits[0] = new VisitInfo(TRANSITION_RELOAD + 1);
try {
yield promiseUpdatePlaces(place);
do_throw("Should have thrown!");
@ -647,9 +647,8 @@ add_task(function* test_add_visit() {
title: "test_add_visit title",
visits: [],
};
for (let transitionType = TRANSITION_LINK;
transitionType <= TRANSITION_FRAMED_LINK;
transitionType++) {
for (let t in PlacesUtils.history.TRANSITIONS) {
let transitionType = PlacesUtils.history.TRANSITIONS[t];
place.visits.push(new VisitInfo(transitionType, VISIT_TIME));
}
do_check_false(yield promiseIsURIVisited(place.uri));
@ -672,8 +671,8 @@ add_task(function* test_add_visit() {
do_check_eq(visits.length, 1);
let visit = visits[0];
do_check_eq(visit.visitDate, VISIT_TIME);
do_check_true(visit.transitionType >= TRANSITION_LINK &&
visit.transitionType <= TRANSITION_FRAMED_LINK);
let transitions =
do_check_true(Object.values(PlacesUtils.history.TRANSITIONS).includes(visit.transitionType));
do_check_true(visit.referrerURI === null);
// For TRANSITION_EMBED visits, many properties will always be zero or
@ -706,9 +705,8 @@ add_task(function* test_add_visit() {
add_task(function* test_properties_saved() {
// Check each transition type to make sure it is saved properly.
let places = [];
for (let transitionType = TRANSITION_LINK;
transitionType <= TRANSITION_FRAMED_LINK;
transitionType++) {
for (let t in PlacesUtils.history.TRANSITIONS) {
let transitionType = PlacesUtils.history.TRANSITIONS[t];
let place = {
uri: NetUtil.newURI(TEST_DOMAIN + "test_properties_saved/" +
transitionType),

View File

@ -79,7 +79,7 @@ add_task(function* test_history_clear()
PlacesUtils.annotations.EXPIRE_NEVER);
// Add a bookmark
// Bookmarked page should have history cleared and frecency = -old_visit_count
// Bookmarked page should have history cleared and frecency = -1
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
uri("http://typed.mozilla.org/"),
PlacesUtils.bookmarks.DEFAULT_INDEX,
@ -105,8 +105,7 @@ add_task(function* test_history_clear()
yield PlacesTestUtils.promiseAsyncUpdates();
// Check that frecency for not cleared items (bookmarks) has been converted
// to -MAX(visit_count, 1), so we will be able to recalculate frecency
// starting from most frecent bookmarks.
// to -1.
stmt = mDBConn.createStatement(
"SELECT h.id FROM moz_places h WHERE h.frecency > 0 ");
do_check_false(stmt.executeStep());

View File

@ -23,17 +23,6 @@ const SCHEMES = {
"javascript:": false,
};
const TRANSITIONS = [
TRANSITION_LINK,
TRANSITION_TYPED,
TRANSITION_BOOKMARK,
TRANSITION_EMBED,
TRANSITION_FRAMED_LINK,
TRANSITION_REDIRECT_PERMANENT,
TRANSITION_REDIRECT_TEMPORARY,
TRANSITION_DOWNLOAD,
];
var gRunner;
function run_test()
{
@ -49,9 +38,9 @@ function* step()
for (let scheme in SCHEMES) {
do_print("Testing scheme " + scheme);
for (let i = 0; i < TRANSITIONS.length; i++) {
let transition = TRANSITIONS[i];
do_print("With transition " + transition);
for (let t in PlacesUtils.history.TRANSITIONS) {
do_print("With transition " + t);
let transition = PlacesUtils.history.TRANSITIONS[t];
let uri = NetUtil.newURI(scheme + "mozilla.org/");

View File

@ -1133,7 +1133,7 @@ tests.push({
check: function() {
let stmt = mDBConn.createStatement(
`SELECT h.id FROM moz_places h
JOIN moz_historyvisits v ON v.place_id = h.id AND visit_type NOT IN (0,4,7,8)
JOIN moz_historyvisits v ON v.place_id = h.id AND visit_type NOT IN (0,4,7,8,9)
GROUP BY h.id HAVING h.visit_count <> count(*)
UNION ALL
SELECT h.id FROM moz_places h