Bug 561450 - Stop supporting session ids in Places.
r=Mano sr=gavin
This commit is contained in:
@@ -282,7 +282,7 @@ PlacesViewBase.prototype = {
|
||||
}
|
||||
else {
|
||||
let itemId = aPlacesNode.itemId;
|
||||
if (PlacesUtils.uriTypes.indexOf(type) != -1) {
|
||||
if (type == Ci.nsINavHistoryResultNode.RESULT_TYPE_URI) {
|
||||
element = document.createElement("menuitem");
|
||||
element.className = "menuitem-iconic bookmark-item menuitem-with-favicon";
|
||||
element.setAttribute("scheme",
|
||||
|
||||
@@ -459,7 +459,6 @@ PlacesController.prototype = {
|
||||
nodeData["separator"] = true;
|
||||
break;
|
||||
case Ci.nsINavHistoryResultNode.RESULT_TYPE_URI:
|
||||
case Ci.nsINavHistoryResultNode.RESULT_TYPE_VISIT:
|
||||
nodeData["link"] = true;
|
||||
uri = NetUtil.newURI(node.uri);
|
||||
if (PlacesUtils.nodeIsBookmark(node)) {
|
||||
|
||||
@@ -768,7 +768,7 @@ var PlacesSearchBox = {
|
||||
query.searchTerms = filterString;
|
||||
var options = currentOptions.clone();
|
||||
// Make sure we're getting uri results.
|
||||
options.resultType = currentOptions.RESULT_TYPE_URI;
|
||||
options.resultType = currentOptions.RESULTS_AS_URI;
|
||||
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
|
||||
options.includeHidden = true;
|
||||
currentView.load([query], options);
|
||||
@@ -784,7 +784,7 @@ var PlacesSearchBox = {
|
||||
query.setTransitions([Ci.nsINavHistoryService.TRANSITION_DOWNLOAD], 1);
|
||||
let options = currentOptions.clone();
|
||||
// Make sure we're getting uri results.
|
||||
options.resultType = currentOptions.RESULT_TYPE_URI;
|
||||
options.resultType = currentOptions.RESULTS_AS_URI;
|
||||
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
|
||||
options.includeHidden = true;
|
||||
currentView.load([query], options);
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
if (PlacesUtils.nodeIsHistoryContainer(queryNode) ||
|
||||
options.resultType == options.RESULTS_AS_TAG_QUERY ||
|
||||
options.resultType == options.RESULTS_AS_TAG_CONTENTS)
|
||||
options.resultType = options.RESULT_TYPE_URI;
|
||||
options.resultType = options.RESULTS_AS_URI;
|
||||
|
||||
var query = PlacesUtils.history.getNewQuery();
|
||||
query.searchTerms = filterString;
|
||||
|
||||
@@ -675,7 +675,7 @@ this.PlacesUIUtils = {
|
||||
|
||||
getBestTitle: function PUIU_getBestTitle(aNode, aDoNotCutTitle) {
|
||||
var title;
|
||||
if (!aNode.title && PlacesUtils.uriTypes.indexOf(aNode.type) != -1) {
|
||||
if (!aNode.title && PlacesUtils.nodeIsURI(aNode)) {
|
||||
// if node title is empty, try to set the label using host and filename
|
||||
// PlacesUtils._uri() will throw if aNode.uri is not a valid URI
|
||||
try {
|
||||
|
||||
@@ -173,9 +173,7 @@ BookmarksView.prototype = {
|
||||
let node = rootNode.getChild(i);
|
||||
|
||||
// Ignore folders, separators, undefined item types, etc.
|
||||
if (node.type != node.RESULT_TYPE_URI &&
|
||||
node.type != node.RESULT_TYPE_VISIT &&
|
||||
node.type != node.RESULT_TYPE_FULL_VISIT)
|
||||
if (node.type != node.RESULT_TYPE_URI)
|
||||
continue;
|
||||
|
||||
this.addBookmark(node.itemId);
|
||||
|
||||
@@ -721,6 +721,13 @@ Database::InitSchema(bool* aDatabaseMigrated)
|
||||
|
||||
// Firefox 14 uses schema version 21.
|
||||
|
||||
if (currentSchemaVersion < 22) {
|
||||
rv = MigrateV22Up();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Firefox 22 uses schema version 22.
|
||||
|
||||
// Schema Upgrades must add migration code here.
|
||||
|
||||
rv = UpdateBookmarkRootTitles();
|
||||
@@ -1873,6 +1880,21 @@ Database::MigrateV21Up()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Database::MigrateV22Up()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Reset all session IDs to 0 since we don't support them anymore.
|
||||
// We don't set them to NULL to avoid breaking downgrades.
|
||||
nsresult rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"UPDATE moz_historyvisits SET session = 0"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
Database::Shutdown()
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
// This is the schema version. Update it at any schema change and add a
|
||||
// corresponding migrateVxx method below.
|
||||
#define DATABASE_SCHEMA_VERSION 21
|
||||
#define DATABASE_SCHEMA_VERSION 22
|
||||
|
||||
// Fired after Places inited.
|
||||
#define TOPIC_PLACES_INIT_COMPLETE "places-init-complete"
|
||||
@@ -272,6 +272,7 @@ protected:
|
||||
nsresult MigrateV19Up();
|
||||
nsresult MigrateV20Up();
|
||||
nsresult MigrateV21Up();
|
||||
nsresult MigrateV22Up();
|
||||
|
||||
nsresult UpdateBookmarkRootTitles();
|
||||
nsresult CheckAndUpdateGUIDs();
|
||||
|
||||
@@ -69,7 +69,6 @@ struct VisitData {
|
||||
VisitData()
|
||||
: placeId(0)
|
||||
, visitId(0)
|
||||
, sessionId(0)
|
||||
, hidden(true)
|
||||
, typed(false)
|
||||
, transitionType(UINT32_MAX)
|
||||
@@ -85,7 +84,6 @@ struct VisitData {
|
||||
nsIURI* aReferrer = NULL)
|
||||
: placeId(0)
|
||||
, visitId(0)
|
||||
, sessionId(0)
|
||||
, hidden(true)
|
||||
, typed(false)
|
||||
, transitionType(UINT32_MAX)
|
||||
@@ -138,7 +136,6 @@ struct VisitData {
|
||||
int64_t placeId;
|
||||
nsCString guid;
|
||||
int64_t visitId;
|
||||
int64_t sessionId;
|
||||
nsCString spec;
|
||||
nsString revHost;
|
||||
bool hidden;
|
||||
@@ -516,9 +513,8 @@ public:
|
||||
// to the database, thus cannot be queried and we don't notify them.
|
||||
if (mPlace.transitionType != nsINavHistoryService::TRANSITION_EMBED) {
|
||||
navHistory->NotifyOnVisit(uri, mPlace.visitId, mPlace.visitTime,
|
||||
mPlace.sessionId, mReferrer.visitId,
|
||||
mPlace.transitionType, mPlace.guid,
|
||||
mPlace.hidden);
|
||||
mReferrer.visitId, mPlace.transitionType,
|
||||
mPlace.guid, mPlace.hidden);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obsService =
|
||||
@@ -612,7 +608,7 @@ public:
|
||||
|
||||
nsCOMPtr<mozIVisitInfo> visit =
|
||||
new VisitInfo(mPlace.visitId, mPlace.visitTime, mPlace.transitionType,
|
||||
referrerURI.forget(), mPlace.sessionId);
|
||||
referrerURI.forget());
|
||||
PlaceInfo::VisitsArray visits;
|
||||
(void)visits.AppendElement(visit);
|
||||
|
||||
@@ -841,26 +837,6 @@ private:
|
||||
for (nsTArray<VisitData>::size_type i = 0; i < mPlaces.Length(); i++) {
|
||||
mReferrers[i].spec = mPlaces[i].referrerSpec;
|
||||
|
||||
// If we are inserting a place into an empty mPlaces array, we need to
|
||||
// check to make sure we do not store a bogus session id that is higher
|
||||
// than the current maximum session id.
|
||||
if (i == 0) {
|
||||
int64_t newSessionId = navHistory->GetNewSessionID();
|
||||
if (mPlaces[0].sessionId > newSessionId) {
|
||||
mPlaces[0].sessionId = newSessionId;
|
||||
}
|
||||
}
|
||||
|
||||
// Speculatively get a new session id for our visit if the current session
|
||||
// id is non-valid or if it is larger than the current largest session id.
|
||||
// While it is true that we will use the session id from the referrer if
|
||||
// the visit was "recent" enough, we cannot call this method off of the
|
||||
// main thread, so we have to consume an id now.
|
||||
if (mPlaces[i].sessionId <= 0 ||
|
||||
(i > 0 && mPlaces[i].sessionId >= mPlaces[0].sessionId)) {
|
||||
mPlaces[i].sessionId = navHistory->GetNewSessionID();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
(void)NS_NewURI(getter_AddRefs(uri), mPlaces[i].spec);
|
||||
@@ -953,7 +929,7 @@ private:
|
||||
// If we have a visitTime, we want information on that specific visit.
|
||||
if (_place.visitTime) {
|
||||
stmt = mHistory->GetStatement(
|
||||
"SELECT id, session, visit_date "
|
||||
"SELECT id, visit_date "
|
||||
"FROM moz_historyvisits "
|
||||
"WHERE place_id = (SELECT id FROM moz_places WHERE url = :page_url) "
|
||||
"AND visit_date = :visit_date "
|
||||
@@ -970,7 +946,7 @@ private:
|
||||
// Otherwise, we want information about the most recent visit.
|
||||
else {
|
||||
stmt = mHistory->GetStatement(
|
||||
"SELECT id, session, visit_date "
|
||||
"SELECT id, visit_date "
|
||||
"FROM moz_historyvisits "
|
||||
"WHERE place_id = (SELECT id FROM moz_places WHERE url = :page_url) "
|
||||
"ORDER BY visit_date DESC "
|
||||
@@ -992,9 +968,7 @@ private:
|
||||
|
||||
rv = stmt->GetInt64(0, &_place.visitId);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
rv = stmt->GetInt64(1, &_place.sessionId);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
rv = stmt->GetInt64(2, reinterpret_cast<int64_t*>(&_place.visitTime));
|
||||
rv = stmt->GetInt64(1, reinterpret_cast<int64_t*>(&_place.visitTime));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
// If we have been given a visit threshold start time, go ahead and
|
||||
@@ -1008,8 +982,8 @@ private:
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches information about a referrer and sets the session id for aPlace if
|
||||
* it was a recent visit or not.
|
||||
* Fetches information about a referrer for aPlace if it was a recent
|
||||
* visit or not.
|
||||
*
|
||||
* @param aReferrer
|
||||
* The VisitData for the referrer. This will be populated with
|
||||
@@ -1025,17 +999,7 @@ private:
|
||||
return;
|
||||
}
|
||||
|
||||
// If we had a referrer, we want to know about its last visit to put this
|
||||
// new visit into the same session.
|
||||
bool recentVisit = FetchVisitInfo(aReferrer, aPlace.visitTime);
|
||||
// At this point, we know the referrer's session id, which this new visit
|
||||
// should also share.
|
||||
if (recentVisit) {
|
||||
aPlace.sessionId = aReferrer.sessionId;
|
||||
}
|
||||
// However, if it isn't recent enough, we don't care to log anything about
|
||||
// the referrer and we'll start a new session.
|
||||
else {
|
||||
if (!FetchVisitInfo(aReferrer, aPlace.visitTime)) {
|
||||
// We must change both the place and referrer to indicate that we will
|
||||
// not be using the referrer's data. This behavior has test coverage, so
|
||||
// if this invariant changes, we'll know.
|
||||
@@ -1061,7 +1025,7 @@ private:
|
||||
stmt = mHistory->GetStatement(
|
||||
"INSERT INTO moz_historyvisits "
|
||||
"(from_visit, place_id, visit_date, visit_type, session) "
|
||||
"VALUES (:from_visit, :page_id, :visit_date, :visit_type, :session) "
|
||||
"VALUES (:from_visit, :page_id, :visit_date, :visit_type, 0) "
|
||||
);
|
||||
NS_ENSURE_STATE(stmt);
|
||||
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("page_id"), _place.placeId);
|
||||
@@ -1071,7 +1035,7 @@ private:
|
||||
stmt = mHistory->GetStatement(
|
||||
"INSERT INTO moz_historyvisits "
|
||||
"(from_visit, place_id, visit_date, visit_type, session) "
|
||||
"VALUES (:from_visit, (SELECT id FROM moz_places WHERE url = :page_url), :visit_date, :visit_type, :session) "
|
||||
"VALUES (:from_visit, (SELECT id FROM moz_places WHERE url = :page_url), :visit_date, :visit_type, 0) "
|
||||
);
|
||||
NS_ENSURE_STATE(stmt);
|
||||
rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), _place.spec);
|
||||
@@ -1090,9 +1054,6 @@ private:
|
||||
rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("visit_type"),
|
||||
transitionType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("session"),
|
||||
_place.sessionId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mozStorageStatementScoper scoper(stmt);
|
||||
rv = stmt->Execute();
|
||||
@@ -2645,15 +2606,6 @@ History::UpdatePlaces(const JS::Value& aPlaceInfos,
|
||||
continue;
|
||||
}
|
||||
|
||||
// The session id is optional.
|
||||
rv = GetIntFromJSObject(aCtx, visit, "sessionId", &data.sessionId);
|
||||
if (rv == NS_ERROR_INVALID_ARG) {
|
||||
data.sessionId = 0;
|
||||
}
|
||||
else {
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// The referrer is optional.
|
||||
nsCOMPtr<nsIURI> referrer = GetURIFromJSObject(aCtx, visit,
|
||||
"referrerURI");
|
||||
|
||||
@@ -44,6 +44,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Deprecated",
|
||||
"resource://gre/modules/Deprecated.jsm");
|
||||
|
||||
// The minimum amount of transactions before starting a batch. Usually we do
|
||||
// do incremental updates, a batch will cause views to completely
|
||||
// refresh instead.
|
||||
@@ -67,7 +70,12 @@ function QI_node(aNode, aIID) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function asVisit(aNode) QI_node(aNode, Ci.nsINavHistoryVisitResultNode);
|
||||
function asVisit(aNode) {
|
||||
Deprecated.warning(
|
||||
"asVisit is deprecated and will be removed in a future version",
|
||||
"https://bugzilla.mozilla.org/show_bug.cgi?id=561450");
|
||||
return aNode;
|
||||
};
|
||||
function asContainer(aNode) QI_node(aNode, Ci.nsINavHistoryContainerResultNode);
|
||||
function asQuery(aNode) QI_node(aNode, Ci.nsINavHistoryQueryResultNode);
|
||||
|
||||
@@ -171,8 +179,7 @@ this.PlacesUtils = {
|
||||
* @returns true if the node is a Bookmark separator, false otherwise
|
||||
*/
|
||||
nodeIsSeparator: function PU_nodeIsSeparator(aNode) {
|
||||
|
||||
return (aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR);
|
||||
return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -182,8 +189,13 @@ this.PlacesUtils = {
|
||||
* @returns true if the node is a visit item, false otherwise
|
||||
*/
|
||||
nodeIsVisit: function PU_nodeIsVisit(aNode) {
|
||||
var type = aNode.type;
|
||||
return type == Ci.nsINavHistoryResultNode.RESULT_TYPE_VISIT;
|
||||
Deprecated.warning(
|
||||
"nodeIsVisit is deprecated ans will be removed in a future version",
|
||||
"https://bugzilla.mozilla.org/show_bug.cgi?id=561450");
|
||||
return this.nodeIsURI(aNode) && aNode.parent &&
|
||||
this.nodeIsQuery(aNode.parent) &&
|
||||
asQuery(aNode.parent).queryOptions.resultType ==
|
||||
Ci.nsINavHistoryQueryOptions.RESULTS_AS_VISIT;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -192,10 +204,14 @@ this.PlacesUtils = {
|
||||
* A result node
|
||||
* @returns true if the node is a URL item, false otherwise
|
||||
*/
|
||||
uriTypes: [Ci.nsINavHistoryResultNode.RESULT_TYPE_URI,
|
||||
Ci.nsINavHistoryResultNode.RESULT_TYPE_VISIT],
|
||||
get uriTypes() {
|
||||
Deprecated.warning(
|
||||
"uriTypes is deprecated ans will be removed in a future version",
|
||||
"https://bugzilla.mozilla.org/show_bug.cgi?id=561450");
|
||||
return [Ci.nsINavHistoryResultNode.RESULT_TYPE_URI];
|
||||
},
|
||||
nodeIsURI: function PU_nodeIsURI(aNode) {
|
||||
return this.uriTypes.indexOf(aNode.type) != -1;
|
||||
return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_URI;
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,13 +14,11 @@ namespace places {
|
||||
VisitInfo::VisitInfo(int64_t aVisitId,
|
||||
PRTime aVisitDate,
|
||||
uint32_t aTransitionType,
|
||||
already_AddRefed<nsIURI> aReferrer,
|
||||
int64_t aSessionId)
|
||||
already_AddRefed<nsIURI> aReferrer)
|
||||
: mVisitId(aVisitId)
|
||||
, mVisitDate(aVisitDate)
|
||||
, mTransitionType(aTransitionType)
|
||||
, mReferrer(aReferrer)
|
||||
, mSessionId(aSessionId)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -55,13 +53,6 @@ VisitInfo::GetReferrerURI(nsIURI** _referrer)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
VisitInfo::GetSessionId(int64_t* _sessionId)
|
||||
{
|
||||
*_sessionId = mSessionId;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// nsISupports
|
||||
|
||||
|
||||
@@ -21,14 +21,13 @@ public:
|
||||
NS_DECL_MOZIVISITINFO
|
||||
|
||||
VisitInfo(int64_t aVisitId, PRTime aVisitDate, uint32_t aTransitionType,
|
||||
already_AddRefed<nsIURI> aReferrer, int64_t aSessionId);
|
||||
already_AddRefed<nsIURI> aReferrer);
|
||||
|
||||
private:
|
||||
const int64_t mVisitId;
|
||||
const PRTime mVisitDate;
|
||||
const uint32_t mTransitionType;
|
||||
nsCOMPtr<nsIURI> mReferrer;
|
||||
const int64_t mSessionId;
|
||||
};
|
||||
|
||||
} // namespace places
|
||||
|
||||
@@ -11,7 +11,7 @@ interface nsIVariant;
|
||||
#include "jsapi.h"
|
||||
%}
|
||||
|
||||
[scriptable, uuid(1a3b1260-4bdb-45d0-a306-dc377dd9baa4)]
|
||||
[scriptable, uuid(41e4ccc9-f0c8-4cd7-9753-7a38514b8488)]
|
||||
interface mozIVisitInfo : nsISupports
|
||||
{
|
||||
/**
|
||||
@@ -36,13 +36,6 @@ interface mozIVisitInfo : nsISupports
|
||||
* The referring URI of this visit. This may be null.
|
||||
*/
|
||||
readonly attribute nsIURI referrerURI;
|
||||
|
||||
/**
|
||||
* The sessionId of this visit.
|
||||
*
|
||||
* @see nsINavHistory.idl
|
||||
*/
|
||||
readonly attribute long long sessionId;
|
||||
};
|
||||
|
||||
[scriptable, uuid(ad83e137-c92a-4b7b-b67e-0a318811f91e)]
|
||||
|
||||
@@ -50,11 +50,14 @@ interface nsINavHistoryResultNode : nsISupports
|
||||
* corresponding specialized result node interface.
|
||||
*/
|
||||
const unsigned long RESULT_TYPE_URI = 0; // nsINavHistoryResultNode
|
||||
const unsigned long RESULT_TYPE_VISIT = 1; // nsINavHistoryVisitResultNode
|
||||
|
||||
// Visit nodes are deprecated and unsupported.
|
||||
// This line exists just to avoid reusing the value:
|
||||
// const unsigned long RESULT_TYPE_VISIT = 1;
|
||||
|
||||
// Full visit nodes are deprecated and unsupported.
|
||||
// This line exists just to avoid reusing the value:
|
||||
// const unsigned long RESULT_TYPE_FULL_VISIT = 2; // nsINavHistoryFullVisitResultNode
|
||||
// const unsigned long RESULT_TYPE_FULL_VISIT = 2;
|
||||
|
||||
// Dynamic containers are deprecated and unsupported.
|
||||
// This const exists just to avoid reusing the value:
|
||||
@@ -154,22 +157,6 @@ interface nsINavHistoryResultNode : nsISupports
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* When you request RESULT_TYPE_VISIT from query options, you will get this
|
||||
* interface for each item, which includes the session ID so that we can
|
||||
* group items from the same session together.
|
||||
*/
|
||||
[scriptable, uuid(8e2c5a86-b33d-4fa6-944b-559af7e95fcd)]
|
||||
interface nsINavHistoryVisitResultNode : nsINavHistoryResultNode
|
||||
{
|
||||
/**
|
||||
* This indicates the session ID of the * visit. This is used for session
|
||||
* grouping when a tree view is sorted by date.
|
||||
*/
|
||||
readonly attribute long long sessionId;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Base class for container results. This includes all types of groupings.
|
||||
* Bookmark folders and places queries will be QueryResultNodes which extends
|
||||
@@ -636,7 +623,7 @@ interface nsINavHistoryObserver : nsISupports
|
||||
*
|
||||
* @param aVisitID ID of the visit that was just created.
|
||||
* @param aTime Time of the visit
|
||||
* @param aSessionID The ID of one connected sequence of visits.
|
||||
* @param aSessionID No longer supported (always set to 0).
|
||||
* @param aReferringID The ID of the visit the user came from. 0 if empty.
|
||||
* @param aTransitionType One of nsINavHistory.TRANSITION_*
|
||||
* @param aGUID The unique ID associated with the page.
|
||||
@@ -1304,7 +1291,7 @@ interface nsINavHistoryService : nsISupports
|
||||
|
||||
/**
|
||||
* Returns true if this URI would be added to the history. You don't have to
|
||||
* worry about calling this, addPageToSession/addURI will always check before
|
||||
* worry about calling this, adding a visit will always check before
|
||||
* actually adding the page. This function is public because some components
|
||||
* may want to check if this page would go in the history (i.e. for
|
||||
* annotations).
|
||||
|
||||
@@ -50,10 +50,10 @@
|
||||
using namespace mozilla;
|
||||
|
||||
// These columns sit to the right of the kGetInfoIndex_* columns.
|
||||
const int32_t nsNavBookmarks::kGetChildrenIndex_Position = 15;
|
||||
const int32_t nsNavBookmarks::kGetChildrenIndex_Type = 16;
|
||||
const int32_t nsNavBookmarks::kGetChildrenIndex_PlaceID = 17;
|
||||
const int32_t nsNavBookmarks::kGetChildrenIndex_Guid = 18;
|
||||
const int32_t nsNavBookmarks::kGetChildrenIndex_Position = 14;
|
||||
const int32_t nsNavBookmarks::kGetChildrenIndex_Type = 15;
|
||||
const int32_t nsNavBookmarks::kGetChildrenIndex_PlaceID = 16;
|
||||
const int32_t nsNavBookmarks::kGetChildrenIndex_Guid = 17;
|
||||
|
||||
using namespace mozilla::places;
|
||||
|
||||
@@ -1061,7 +1061,7 @@ nsNavBookmarks::GetDescendantChildren(int64_t aFolderId,
|
||||
// item_child, and folder_child from moz_bookmarks.
|
||||
nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
|
||||
"SELECT h.id, h.url, IFNULL(b.title, h.title), h.rev_host, h.visit_count, "
|
||||
"h.last_visit_date, f.url, null, b.id, b.dateAdded, b.lastModified, "
|
||||
"h.last_visit_date, f.url, b.id, b.dateAdded, b.lastModified, "
|
||||
"b.parent, null, h.frecency, h.hidden, b.position, b.type, b.fk, "
|
||||
"b.guid "
|
||||
"FROM moz_bookmarks b "
|
||||
@@ -1765,7 +1765,7 @@ nsNavBookmarks::QueryFolderChildren(
|
||||
// item_child, and folder_child from moz_bookmarks.
|
||||
nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
|
||||
"SELECT h.id, h.url, IFNULL(b.title, h.title), h.rev_host, h.visit_count, "
|
||||
"h.last_visit_date, f.url, null, b.id, b.dateAdded, b.lastModified, "
|
||||
"h.last_visit_date, f.url, b.id, b.dateAdded, b.lastModified, "
|
||||
"b.parent, null, h.frecency, h.hidden, b.position, b.type, b.fk, "
|
||||
"b.guid "
|
||||
"FROM moz_bookmarks b "
|
||||
@@ -1899,7 +1899,7 @@ nsNavBookmarks::QueryFolderChildrenAsync(
|
||||
// item_child, and folder_child from moz_bookmarks.
|
||||
nsCOMPtr<mozIStorageAsyncStatement> stmt = mDB->GetAsyncStatement(
|
||||
"SELECT h.id, h.url, IFNULL(b.title, h.title), h.rev_host, h.visit_count, "
|
||||
"h.last_visit_date, f.url, null, b.id, b.dateAdded, b.lastModified, "
|
||||
"h.last_visit_date, f.url, b.id, b.dateAdded, b.lastModified, "
|
||||
"b.parent, null, h.frecency, h.hidden, b.position, b.type, b.fk, "
|
||||
"b.guid "
|
||||
"FROM moz_bookmarks b "
|
||||
|
||||
@@ -243,14 +243,13 @@ const int32_t nsNavHistory::kGetInfoIndex_RevHost = 3;
|
||||
const int32_t nsNavHistory::kGetInfoIndex_VisitCount = 4;
|
||||
const int32_t nsNavHistory::kGetInfoIndex_VisitDate = 5;
|
||||
const int32_t nsNavHistory::kGetInfoIndex_FaviconURL = 6;
|
||||
const int32_t nsNavHistory::kGetInfoIndex_SessionId = 7;
|
||||
const int32_t nsNavHistory::kGetInfoIndex_ItemId = 8;
|
||||
const int32_t nsNavHistory::kGetInfoIndex_ItemDateAdded = 9;
|
||||
const int32_t nsNavHistory::kGetInfoIndex_ItemLastModified = 10;
|
||||
const int32_t nsNavHistory::kGetInfoIndex_ItemParentId = 11;
|
||||
const int32_t nsNavHistory::kGetInfoIndex_ItemTags = 12;
|
||||
const int32_t nsNavHistory::kGetInfoIndex_Frecency = 13;
|
||||
const int32_t nsNavHistory::kGetInfoIndex_Hidden = 14;
|
||||
const int32_t nsNavHistory::kGetInfoIndex_ItemId = 7;
|
||||
const int32_t nsNavHistory::kGetInfoIndex_ItemDateAdded = 8;
|
||||
const int32_t nsNavHistory::kGetInfoIndex_ItemLastModified = 9;
|
||||
const int32_t nsNavHistory::kGetInfoIndex_ItemParentId = 10;
|
||||
const int32_t nsNavHistory::kGetInfoIndex_ItemTags = 11;
|
||||
const int32_t nsNavHistory::kGetInfoIndex_Frecency = 12;
|
||||
const int32_t nsNavHistory::kGetInfoIndex_Hidden = 13;
|
||||
|
||||
PLACES_FACTORY_SINGLETON_IMPLEMENTATION(nsNavHistory, gHistoryService)
|
||||
|
||||
@@ -260,7 +259,6 @@ nsNavHistory::nsNavHistory()
|
||||
, mBatchDBTransaction(nullptr)
|
||||
, mCachedNow(0)
|
||||
, mExpireNowTimer(nullptr)
|
||||
, mLastSessionID(0)
|
||||
, mHistoryEnabled(true)
|
||||
, mNumVisitsForFrecency(10)
|
||||
, mTagsFolder(-1)
|
||||
@@ -505,38 +503,10 @@ nsNavHistory::LoadPrefs()
|
||||
}
|
||||
|
||||
|
||||
int64_t
|
||||
nsNavHistory::GetNewSessionID()
|
||||
{
|
||||
// Use cached value if already initialized.
|
||||
if (mLastSessionID)
|
||||
return ++mLastSessionID;
|
||||
|
||||
// Extract the last session ID, so we know where to pick up. There is no
|
||||
// index over sessions so we use the visit_date index.
|
||||
nsCOMPtr<mozIStorageStatement> selectSession;
|
||||
nsresult rv = mDB->MainConn()->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT session FROM moz_historyvisits "
|
||||
"ORDER BY visit_date DESC "
|
||||
), getter_AddRefs(selectSession));
|
||||
NS_ENSURE_SUCCESS(rv, 0);
|
||||
bool hasSession;
|
||||
if (NS_SUCCEEDED(selectSession->ExecuteStep(&hasSession)) && hasSession) {
|
||||
mLastSessionID = selectSession->AsInt64(0) + 1;
|
||||
}
|
||||
else {
|
||||
mLastSessionID = 1;
|
||||
}
|
||||
|
||||
return mLastSessionID;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsNavHistory::NotifyOnVisit(nsIURI* aURI,
|
||||
int64_t aVisitID,
|
||||
PRTime aTime,
|
||||
int64_t aSessionID,
|
||||
int64_t referringVisitID,
|
||||
int32_t aTransitionType,
|
||||
const nsACString& aGUID,
|
||||
@@ -555,7 +525,7 @@ nsNavHistory::NotifyOnVisit(nsIURI* aURI,
|
||||
|
||||
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
|
||||
nsINavHistoryObserver,
|
||||
OnVisit(aURI, aVisitID, aTime, aSessionID,
|
||||
OnVisit(aURI, aVisitID, aTime, 0,
|
||||
referringVisitID, aTransitionType, aGUID, aHidden));
|
||||
}
|
||||
|
||||
@@ -1424,7 +1394,7 @@ PlacesSQLQueryBuilder::SelectAsURI()
|
||||
|
||||
mQueryString = NS_LITERAL_CSTRING(
|
||||
"SELECT h.id, h.url, h.title AS page_title, h.rev_host, h.visit_count, "
|
||||
"h.last_visit_date, f.url, null, null, null, null, null, ") +
|
||||
"h.last_visit_date, f.url, null, null, null, null, ") +
|
||||
tagsSqlFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden "
|
||||
"FROM moz_places h "
|
||||
"LEFT JOIN moz_favicons f ON h.favicon_id = f.id "
|
||||
@@ -1449,7 +1419,7 @@ PlacesSQLQueryBuilder::SelectAsURI()
|
||||
|
||||
mQueryString = NS_LITERAL_CSTRING(
|
||||
"SELECT b2.fk, h.url, COALESCE(b2.title, h.title) AS page_title, "
|
||||
"h.rev_host, h.visit_count, h.last_visit_date, f.url, null, b2.id, "
|
||||
"h.rev_host, h.visit_count, h.last_visit_date, f.url, b2.id, "
|
||||
"b2.dateAdded, b2.lastModified, b2.parent, ") +
|
||||
tagsSqlFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden "
|
||||
"FROM moz_bookmarks b2 "
|
||||
@@ -1473,7 +1443,7 @@ PlacesSQLQueryBuilder::SelectAsURI()
|
||||
tagsSqlFragment);
|
||||
mQueryString = NS_LITERAL_CSTRING(
|
||||
"SELECT b.fk, h.url, COALESCE(b.title, h.title) AS page_title, "
|
||||
"h.rev_host, h.visit_count, h.last_visit_date, f.url, null, b.id, "
|
||||
"h.rev_host, h.visit_count, h.last_visit_date, f.url, b.id, "
|
||||
"b.dateAdded, b.lastModified, b.parent, ") +
|
||||
tagsSqlFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden "
|
||||
"FROM moz_bookmarks b "
|
||||
@@ -1506,7 +1476,7 @@ PlacesSQLQueryBuilder::SelectAsVisit()
|
||||
tagsSqlFragment);
|
||||
mQueryString = NS_LITERAL_CSTRING(
|
||||
"SELECT h.id, h.url, h.title AS page_title, h.rev_host, h.visit_count, "
|
||||
"v.visit_date, f.url, v.session, null, null, null, null, ") +
|
||||
"v.visit_date, f.url, null, null, null, null, ") +
|
||||
tagsSqlFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden "
|
||||
"FROM moz_places h "
|
||||
"JOIN moz_historyvisits v ON h.id = v.place_id "
|
||||
@@ -1542,7 +1512,7 @@ PlacesSQLQueryBuilder::SelectAsDay()
|
||||
mQueryString = nsPrintfCString(
|
||||
"SELECT null, "
|
||||
"'place:type=%ld&sort=%ld&beginTime='||beginTime||'&endTime='||endTime, "
|
||||
"dayTitle, null, null, beginTime, null, null, null, null, null, null, null "
|
||||
"dayTitle, null, null, beginTime, null, null, null, null, null, null "
|
||||
"FROM (", // TOUTER BEGIN
|
||||
resultType,
|
||||
sortingMode);
|
||||
@@ -1745,7 +1715,7 @@ PlacesSQLQueryBuilder::SelectAsSite()
|
||||
|
||||
mQueryString = nsPrintfCString(
|
||||
"SELECT null, 'place:type=%ld&sort=%ld&domain=&domainIsHost=true'%s, "
|
||||
":localhost, :localhost, null, null, null, null, null, null, null, null "
|
||||
":localhost, :localhost, null, null, null, null, null, null, null "
|
||||
"WHERE EXISTS ( "
|
||||
"SELECT h.id FROM moz_places h "
|
||||
"%s "
|
||||
@@ -1758,7 +1728,7 @@ PlacesSQLQueryBuilder::SelectAsSite()
|
||||
"UNION ALL "
|
||||
"SELECT null, "
|
||||
"'place:type=%ld&sort=%ld&domain='||host||'&domainIsHost=true'%s, "
|
||||
"host, host, null, null, null, null, null, null, null, null "
|
||||
"host, host, null, null, null, null, null, null, null "
|
||||
"FROM ( "
|
||||
"SELECT get_unreversed_host(h.rev_host) AS host "
|
||||
"FROM moz_places h "
|
||||
@@ -1797,7 +1767,7 @@ PlacesSQLQueryBuilder::SelectAsTag()
|
||||
|
||||
mQueryString = nsPrintfCString(
|
||||
"SELECT null, 'place:folder=' || id || '&queryType=%d&type=%ld', "
|
||||
"title, null, null, null, null, null, null, dateAdded, "
|
||||
"title, null, null, null, null, null, dateAdded, "
|
||||
"lastModified, null, null, null "
|
||||
"FROM moz_bookmarks "
|
||||
"WHERE parent = %lld",
|
||||
@@ -2031,7 +2001,7 @@ nsNavHistory::ConstructQueryString(
|
||||
// smart bookmark.
|
||||
queryString = NS_LITERAL_CSTRING(
|
||||
"SELECT h.id, h.url, h.title AS page_title, h.rev_host, h.visit_count, h.last_visit_date, "
|
||||
"f.url, null, null, null, null, null, ") +
|
||||
"f.url, null, null, null, null, ") +
|
||||
tagsSqlFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden "
|
||||
"FROM moz_places h "
|
||||
"LEFT OUTER JOIN moz_favicons f ON h.favicon_id = f.id "
|
||||
@@ -3881,15 +3851,10 @@ nsNavHistory::RowToResult(mozIStorageValueArray* aRow,
|
||||
resultNode.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
// now we know the result type is some kind of visit (regular or full)
|
||||
|
||||
// session
|
||||
int64_t session = aRow->AsInt64(kGetInfoIndex_SessionId);
|
||||
|
||||
if (aOptions->ResultType() == nsNavHistoryQueryOptions::RESULTS_AS_VISIT) {
|
||||
nsRefPtr<nsNavHistoryResultNode> resultNode =
|
||||
new nsNavHistoryVisitResultNode(url, title, accessCount, time,
|
||||
favicon, session);
|
||||
new nsNavHistoryResultNode(url, title, accessCount, time, favicon);
|
||||
|
||||
nsAutoString tags;
|
||||
rv = aRow->GetString(kGetInfoIndex_ItemTags, tags);
|
||||
@@ -3993,7 +3958,7 @@ nsNavHistory::VisitIdToResultNode(int64_t visitId,
|
||||
// Should match kGetInfoIndex_* (see GetQueryResults)
|
||||
statement = mDB->GetStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT h.id, h.url, h.title, h.rev_host, h.visit_count, "
|
||||
"v.visit_date, f.url, v.session, null, null, null, null, "
|
||||
"v.visit_date, f.url, null, null, null, null, "
|
||||
) + tagsFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden "
|
||||
"FROM moz_places h "
|
||||
"JOIN moz_historyvisits v ON h.id = v.place_id "
|
||||
@@ -4007,7 +3972,7 @@ nsNavHistory::VisitIdToResultNode(int64_t visitId,
|
||||
// Should match kGetInfoIndex_* (see GetQueryResults)
|
||||
statement = mDB->GetStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT h.id, h.url, h.title, h.rev_host, h.visit_count, "
|
||||
"h.last_visit_date, f.url, null, null, null, null, null, "
|
||||
"h.last_visit_date, f.url, null, null, null, null, "
|
||||
) + tagsFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden "
|
||||
"FROM moz_places h "
|
||||
"JOIN moz_historyvisits v ON h.id = v.place_id "
|
||||
@@ -4052,7 +4017,7 @@ nsNavHistory::BookmarkIdToResultNode(int64_t aBookmarkId, nsNavHistoryQueryOptio
|
||||
// Should match kGetInfoIndex_*
|
||||
nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT b.fk, h.url, COALESCE(b.title, h.title), "
|
||||
"h.rev_host, h.visit_count, h.last_visit_date, f.url, null, b.id, "
|
||||
"h.rev_host, h.visit_count, h.last_visit_date, f.url, b.id, "
|
||||
"b.dateAdded, b.lastModified, b.parent, "
|
||||
) + tagsFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden "
|
||||
"FROM moz_bookmarks b "
|
||||
@@ -4092,7 +4057,7 @@ nsNavHistory::URIToResultNode(nsIURI* aURI,
|
||||
// Should match kGetInfoIndex_*
|
||||
nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT h.id, :page_url, h.title, h.rev_host, h.visit_count, "
|
||||
"h.last_visit_date, f.url, null, null, null, null, null, "
|
||||
"h.last_visit_date, f.url, null, null, null, null, "
|
||||
) + tagsFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden "
|
||||
"FROM moz_places h "
|
||||
"LEFT JOIN moz_favicons f ON h.favicon_id = f.id "
|
||||
|
||||
@@ -210,7 +210,6 @@ public:
|
||||
static const int32_t kGetInfoIndex_VisitCount;
|
||||
static const int32_t kGetInfoIndex_VisitDate;
|
||||
static const int32_t kGetInfoIndex_FaviconURL;
|
||||
static const int32_t kGetInfoIndex_SessionId;
|
||||
static const int32_t kGetInfoIndex_ItemId;
|
||||
static const int32_t kGetInfoIndex_ItemDateAdded;
|
||||
static const int32_t kGetInfoIndex_ItemLastModified;
|
||||
@@ -401,15 +400,12 @@ public:
|
||||
return mNumVisitsForFrecency;
|
||||
}
|
||||
|
||||
int64_t GetNewSessionID();
|
||||
|
||||
/**
|
||||
* Fires onVisit event to nsINavHistoryService observers
|
||||
*/
|
||||
void NotifyOnVisit(nsIURI* aURI,
|
||||
int64_t aVisitID,
|
||||
PRTime aTime,
|
||||
int64_t aSessionID,
|
||||
int64_t referringVisitID,
|
||||
int32_t aTransitionType,
|
||||
const nsACString& aGUID,
|
||||
@@ -536,9 +532,6 @@ protected:
|
||||
const nsACString& url);
|
||||
void ExpireNonrecentEvents(RecentEventHash* hashTable);
|
||||
|
||||
// Sessions tracking.
|
||||
int64_t mLastSessionID;
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
nsresult AutoCompleteFeedback(int32_t aIndex,
|
||||
nsIAutoCompleteController *aController);
|
||||
|
||||
@@ -292,19 +292,6 @@ nsNavHistoryResultNode::GetGeneratingOptions()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsNavHistoryVisitResultNode,
|
||||
nsNavHistoryResultNode,
|
||||
nsINavHistoryVisitResultNode)
|
||||
|
||||
nsNavHistoryVisitResultNode::nsNavHistoryVisitResultNode(
|
||||
const nsACString& aURI, const nsACString& aTitle, uint32_t aAccessCount,
|
||||
PRTime aTime, const nsACString& aIconURI, int64_t aSession) :
|
||||
nsNavHistoryResultNode(aURI, aTitle, aAccessCount, aTime, aIconURI),
|
||||
mSessionId(aSession)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsNavHistoryContainerResultNode, nsNavHistoryResultNode)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mResult)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildren)
|
||||
@@ -2491,7 +2478,7 @@ nsNavHistoryQueryResultNode::OnVisit(nsIURI* aURI, int64_t aVisitId,
|
||||
if (!history->EvaluateQueryForNode(mQueries, mOptions, addition))
|
||||
return NS_OK; // don't need to include in our query
|
||||
|
||||
if (addition->IsVisit()) {
|
||||
if (mOptions->ResultType() == nsNavHistoryQueryOptions::RESULTS_AS_VISIT) {
|
||||
// If this is a visit type query, just insert the new visit. We never
|
||||
// update visits, only add or remove them.
|
||||
rv = InsertSortedChild(addition);
|
||||
|
||||
@@ -26,7 +26,6 @@ class nsNavHistoryQueryOptions;
|
||||
class nsNavHistoryContainerResultNode;
|
||||
class nsNavHistoryFolderResultNode;
|
||||
class nsNavHistoryQueryResultNode;
|
||||
class nsNavHistoryVisitResultNode;
|
||||
|
||||
/**
|
||||
* hashkey wrapper using int64_t KeyType
|
||||
@@ -290,9 +289,9 @@ public:
|
||||
// would take a vtable slot for every one of (potentially very many) nodes.
|
||||
// Note that GetType() already has a vtable slot because its on the iface.
|
||||
bool IsTypeContainer(uint32_t type) {
|
||||
return (type == nsINavHistoryResultNode::RESULT_TYPE_QUERY ||
|
||||
return type == nsINavHistoryResultNode::RESULT_TYPE_QUERY ||
|
||||
type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER ||
|
||||
type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT);
|
||||
type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT;
|
||||
}
|
||||
bool IsContainer() {
|
||||
uint32_t type;
|
||||
@@ -300,25 +299,16 @@ public:
|
||||
return IsTypeContainer(type);
|
||||
}
|
||||
static bool IsTypeURI(uint32_t type) {
|
||||
return (type == nsINavHistoryResultNode::RESULT_TYPE_URI ||
|
||||
type == nsINavHistoryResultNode::RESULT_TYPE_VISIT);
|
||||
return type == nsINavHistoryResultNode::RESULT_TYPE_URI;
|
||||
}
|
||||
bool IsURI() {
|
||||
uint32_t type;
|
||||
GetType(&type);
|
||||
return IsTypeURI(type);
|
||||
}
|
||||
static bool IsTypeVisit(uint32_t type) {
|
||||
return type == nsINavHistoryResultNode::RESULT_TYPE_VISIT;
|
||||
}
|
||||
bool IsVisit() {
|
||||
uint32_t type;
|
||||
GetType(&type);
|
||||
return IsTypeVisit(type);
|
||||
}
|
||||
static bool IsTypeFolder(uint32_t type) {
|
||||
return (type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER ||
|
||||
type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT);
|
||||
return type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER ||
|
||||
type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT;
|
||||
}
|
||||
bool IsFolder() {
|
||||
uint32_t type;
|
||||
@@ -326,7 +316,7 @@ public:
|
||||
return IsTypeFolder(type);
|
||||
}
|
||||
static bool IsTypeQuery(uint32_t type) {
|
||||
return (type == nsINavHistoryResultNode::RESULT_TYPE_QUERY);
|
||||
return type == nsINavHistoryResultNode::RESULT_TYPE_QUERY;
|
||||
}
|
||||
bool IsQuery() {
|
||||
uint32_t type;
|
||||
@@ -336,16 +326,12 @@ public:
|
||||
bool IsSeparator() {
|
||||
uint32_t type;
|
||||
GetType(&type);
|
||||
return (type == nsINavHistoryResultNode::RESULT_TYPE_SEPARATOR);
|
||||
return type == nsINavHistoryResultNode::RESULT_TYPE_SEPARATOR;
|
||||
}
|
||||
nsNavHistoryContainerResultNode* GetAsContainer() {
|
||||
NS_ASSERTION(IsContainer(), "Not a container");
|
||||
return reinterpret_cast<nsNavHistoryContainerResultNode*>(this);
|
||||
}
|
||||
nsNavHistoryVisitResultNode* GetAsVisit() {
|
||||
NS_ASSERTION(IsVisit(), "Not a visit");
|
||||
return reinterpret_cast<nsNavHistoryVisitResultNode*>(this);
|
||||
}
|
||||
nsNavHistoryFolderResultNode* GetAsFolder() {
|
||||
NS_ASSERTION(IsFolder(), "Not a folder");
|
||||
return reinterpret_cast<nsNavHistoryFolderResultNode*>(this);
|
||||
@@ -385,32 +371,6 @@ public:
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResultNode, NS_NAVHISTORYRESULTNODE_IID)
|
||||
|
||||
// nsNavHistoryVisitResultNode
|
||||
|
||||
#define NS_IMPLEMENT_VISITRESULT \
|
||||
NS_IMETHOD GetUri(nsACString& aURI) { aURI = mURI; return NS_OK; } \
|
||||
NS_IMETHOD GetSessionId(int64_t* aSessionId) \
|
||||
{ *aSessionId = mSessionId; return NS_OK; }
|
||||
|
||||
class nsNavHistoryVisitResultNode : public nsNavHistoryResultNode,
|
||||
public nsINavHistoryVisitResultNode
|
||||
{
|
||||
public:
|
||||
nsNavHistoryVisitResultNode(const nsACString& aURI, const nsACString& aTitle,
|
||||
uint32_t aAccessCount, PRTime aTime,
|
||||
const nsACString& aIconURI, int64_t aSession);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_FORWARD_COMMON_RESULTNODE_TO_BASE
|
||||
NS_IMETHOD GetType(uint32_t* type)
|
||||
{ *type = nsNavHistoryResultNode::RESULT_TYPE_VISIT; return NS_OK; }
|
||||
NS_IMPLEMENT_VISITRESULT
|
||||
|
||||
public:
|
||||
|
||||
int64_t mSessionId;
|
||||
};
|
||||
|
||||
|
||||
// nsNavHistoryContainerResultNode
|
||||
//
|
||||
|
||||
@@ -239,7 +239,6 @@ function isBookmarkAltered(aWin){
|
||||
let options = aWin.PlacesUtils.history.getNewQueryOptions();
|
||||
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS;
|
||||
options.maxResults = 1; // should only expect a new bookmark
|
||||
options.resultType = options.RESULT_TYPE_VISIT;
|
||||
|
||||
let query = aWin.PlacesUtils.history.getNewQuery();
|
||||
query.setFolders([aWin.PlacesUtils.bookmarks.bookmarksMenuFolder], 1);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const CURRENT_SCHEMA_VERSION = 21;
|
||||
const CURRENT_SCHEMA_VERSION = 22;
|
||||
|
||||
const NS_APP_USER_PROFILE_50_DIR = "ProfD";
|
||||
const NS_APP_PROFILE_DIR_STARTUP = "ProfDS";
|
||||
|
||||
@@ -19,8 +19,6 @@ HTTPSVR.registerPathHandler(PERMA_REDIR_PATH, permaRedirHandler);
|
||||
HTTPSVR.registerPathHandler(TEMP_REDIR_PATH, tempRedirHandler);
|
||||
HTTPSVR.registerPathHandler(FOUND_PATH, foundHandler);
|
||||
|
||||
const EXPECTED_SESSION_ID = 1;
|
||||
|
||||
const STATUS = {
|
||||
REDIRECT_PERMANENT: [301, "Moved Permanently"],
|
||||
REDIRECT_TEMPORARY: [302, "Moved"],
|
||||
@@ -75,7 +73,7 @@ function run_test() {
|
||||
|
||||
function continue_test() {
|
||||
let stmt = DBConn().createStatement(
|
||||
"SELECT v.id, h.url, v.from_visit, v.visit_date, v.visit_type, v.session " +
|
||||
"SELECT v.id, h.url, v.from_visit, v.visit_date, v.visit_type " +
|
||||
"FROM moz_historyvisits v " +
|
||||
"JOIN moz_places h on h.id = v.place_id " +
|
||||
"ORDER BY v.id ASC");
|
||||
@@ -83,18 +81,15 @@ function continue_test() {
|
||||
{ id: 1,
|
||||
url: PERMA_REDIR_URL,
|
||||
from_visit: 0,
|
||||
visit_type: Ci.nsINavHistoryService.TRANSITION_LINK,
|
||||
session: EXPECTED_SESSION_ID },
|
||||
visit_type: Ci.nsINavHistoryService.TRANSITION_LINK },
|
||||
{ id: 2,
|
||||
url: TEMP_REDIR_URL,
|
||||
from_visit: 1,
|
||||
visit_type: Ci.nsINavHistoryService.TRANSITION_REDIRECT_PERMANENT,
|
||||
session: EXPECTED_SESSION_ID },
|
||||
visit_type: Ci.nsINavHistoryService.TRANSITION_REDIRECT_PERMANENT },
|
||||
{ id: 3,
|
||||
url: FOUND_URL,
|
||||
from_visit: 2,
|
||||
visit_type: Ci.nsINavHistoryService.TRANSITION_REDIRECT_TEMPORARY,
|
||||
session: EXPECTED_SESSION_ID },
|
||||
visit_type: Ci.nsINavHistoryService.TRANSITION_REDIRECT_TEMPORARY },
|
||||
];
|
||||
try {
|
||||
while(stmt.executeStep()) {
|
||||
@@ -105,7 +100,6 @@ function continue_test() {
|
||||
do_check_eq(stmt.row.url, comparator.url);
|
||||
do_check_eq(stmt.row.from_visit, comparator.from_visit);
|
||||
do_check_eq(stmt.row.visit_type, comparator.visit_type);
|
||||
do_check_eq(stmt.row.session, comparator.session);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
|
||||
@@ -55,13 +55,13 @@ add_task(function test_execute()
|
||||
let node = root.getChild(index);
|
||||
let site = "http://www.test-" + (TOTAL_SITES - 1 - i) + ".com/";
|
||||
do_check_eq(node.uri, site);
|
||||
do_check_eq(node.type, options.RESULTS_AS_VISIT);
|
||||
do_check_eq(node.type, Ci.nsINavHistoryResultNode.RESULT_TYPE_URI);
|
||||
node = root.getChild(++index);
|
||||
do_check_eq(node.uri, site + "blank.gif");
|
||||
do_check_eq(node.type, options.RESULTS_AS_VISIT);
|
||||
do_check_eq(node.type, Ci.nsINavHistoryResultNode.RESULT_TYPE_URI);
|
||||
node = root.getChild(++index);
|
||||
do_check_eq(node.uri, site);
|
||||
do_check_eq(node.type, options.RESULTS_AS_VISIT);
|
||||
do_check_eq(node.type, Ci.nsINavHistoryResultNode.RESULT_TYPE_URI);
|
||||
}
|
||||
root.containerOpen = false;
|
||||
|
||||
@@ -86,10 +86,10 @@ add_task(function test_execute()
|
||||
let node = root.getChild(index);
|
||||
let site = "http://www.test-" + (TOTAL_SITES - 1 - i) + ".com/";
|
||||
do_check_eq(node.uri, site);
|
||||
do_check_eq(node.type, options.RESULTS_AS_VISIT);
|
||||
do_check_eq(node.type, Ci.nsINavHistoryResultNode.RESULT_TYPE_URI);
|
||||
node = root.getChild(++index);
|
||||
do_check_eq(node.uri, site);
|
||||
do_check_eq(node.type, options.RESULTS_AS_VISIT);
|
||||
do_check_eq(node.type, Ci.nsINavHistoryResultNode.RESULT_TYPE_URI);
|
||||
}
|
||||
root.containerOpen = false;
|
||||
|
||||
@@ -113,7 +113,7 @@ add_task(function test_execute()
|
||||
let node = root.getChild(i);
|
||||
let site = "http://www.test-" + (TOTAL_SITES - 1 - i) + ".com/";
|
||||
do_check_eq(node.uri, site);
|
||||
do_check_eq(node.type, options.RESULTS_AS_URI);
|
||||
do_check_eq(node.type, Ci.nsINavHistoryResultNode.RESULT_TYPE_URI);
|
||||
}
|
||||
root.containerOpen = false;
|
||||
|
||||
@@ -136,7 +136,7 @@ add_task(function test_execute()
|
||||
let node = root.getChild(i);
|
||||
let site = "http://www.test-" + (TOTAL_SITES - 1 - i) + ".com/";
|
||||
do_check_eq(node.uri, site);
|
||||
do_check_eq(node.type, options.RESULTS_AS_URI);
|
||||
do_check_eq(node.type, Ci.nsINavHistoryResultNode.RESULT_TYPE_URI);
|
||||
}
|
||||
root.containerOpen = false;
|
||||
});
|
||||
|
||||
@@ -49,7 +49,7 @@ add_task(function test_execute()
|
||||
let node = root.getChild(i);
|
||||
let site = "http://www.test-" + (TOTAL_SITES - 1 - i) + ".com/";
|
||||
do_check_eq(node.uri, site);
|
||||
do_check_eq(node.type, options.RESULTS_AS_URI);
|
||||
do_check_eq(node.type, Ci.nsINavHistoryResultNode.RESULT_TYPE_URI);
|
||||
}
|
||||
root.containerOpen = false;
|
||||
|
||||
@@ -72,7 +72,7 @@ add_task(function test_execute()
|
||||
let node = root.getChild(i);
|
||||
let site = "http://www.test-" + (TOTAL_SITES - 1 - i) + ".com/";
|
||||
do_check_eq(node.uri, site);
|
||||
do_check_eq(node.type, options.RESULTS_AS_URI);
|
||||
do_check_eq(node.type, Ci.nsINavHistoryResultNode.RESULT_TYPE_URI);
|
||||
}
|
||||
root.containerOpen = false;
|
||||
});
|
||||
|
||||
@@ -515,93 +515,6 @@ function test_nonnsIURI_referrerURI_ignored()
|
||||
yield promiseAsyncUpdates();
|
||||
}
|
||||
|
||||
function test_invalid_sessionId_ignored()
|
||||
{
|
||||
let place = {
|
||||
uri: NetUtil.newURI(TEST_DOMAIN +
|
||||
"test_invalid_sessionId_ignored"),
|
||||
visits: [
|
||||
new VisitInfo(),
|
||||
],
|
||||
};
|
||||
place.visits[0].sessionId = 0;
|
||||
do_check_false(yield promiseIsURIVisited(place.uri));
|
||||
|
||||
let placesResult = yield promiseUpdatePlaces(place);
|
||||
if (placesResult.errors.length > 0) {
|
||||
do_throw("Unexpected error.");
|
||||
}
|
||||
let placeInfo = placesResult.results[0];
|
||||
do_check_true(yield promiseIsURIVisited(placeInfo.uri));
|
||||
|
||||
// Check to make sure we do not persist bogus sessionId with the visit.
|
||||
let visit = placeInfo.visits[0];
|
||||
do_check_neq(visit.sessionId, place.visits[0].sessionId);
|
||||
|
||||
// Check to make sure we do not persist bogus sessionId in database.
|
||||
let stmt = DBConn().createStatement(
|
||||
"SELECT session " +
|
||||
"FROM moz_historyvisits " +
|
||||
"WHERE id = :visit_id"
|
||||
);
|
||||
stmt.params.visit_id = visit.visitId;
|
||||
do_check_true(stmt.executeStep());
|
||||
do_check_neq(stmt.row.session, place.visits[0].sessionId);
|
||||
stmt.finalize();
|
||||
|
||||
yield promiseAsyncUpdates();
|
||||
}
|
||||
|
||||
function test_unstored_sessionId_ignored()
|
||||
{
|
||||
let place = {
|
||||
uri: NetUtil.newURI(TEST_DOMAIN +
|
||||
"test_unstored_sessionId_ignored"),
|
||||
visits: [
|
||||
new VisitInfo(),
|
||||
],
|
||||
};
|
||||
|
||||
// Find max session id in database.
|
||||
let stmt = DBConn().createStatement(
|
||||
"SELECT MAX(session) as max_session " +
|
||||
"FROM moz_historyvisits"
|
||||
);
|
||||
do_check_true(stmt.executeStep());
|
||||
let maxSessionId = stmt.row.max_session;
|
||||
stmt.finalize();
|
||||
|
||||
// Create bogus sessionId that is not in database.
|
||||
place.visits[0].sessionId = maxSessionId + 10;
|
||||
do_check_false(yield promiseIsURIVisited(place.uri));
|
||||
|
||||
let placesResult = yield promiseUpdatePlaces(place);
|
||||
if (placesResult.errors.length > 0) {
|
||||
do_throw("Unexpected error.");
|
||||
}
|
||||
let placeInfo = placesResult.results[0];
|
||||
do_check_true(yield promiseIsURIVisited(placeInfo.uri));
|
||||
|
||||
// Check to make sure we do not persist bogus sessionId with the visit.
|
||||
let visit = placeInfo.visits[0];
|
||||
do_check_neq(visit.sessionId, place.visits[0].sessionId);
|
||||
|
||||
// Check to make sure we do not persist bogus sessionId in the database.
|
||||
let stmt = DBConn().createStatement(
|
||||
"SELECT MAX(session) as max_session " +
|
||||
"FROM moz_historyvisits"
|
||||
);
|
||||
do_check_true(stmt.executeStep());
|
||||
|
||||
// Max sessionId should increase by 1 because we will generate a new
|
||||
// non-bogus sessionId.
|
||||
let newMaxSessionId = stmt.row.max_session;
|
||||
do_check_eq(maxSessionId + 1, newMaxSessionId);
|
||||
stmt.finalize();
|
||||
|
||||
yield promiseAsyncUpdates();
|
||||
}
|
||||
|
||||
function test_old_referrer_ignored()
|
||||
{
|
||||
// This tests that a referrer for a visit which is not recent (specifically,
|
||||
@@ -791,7 +704,6 @@ function test_add_visit()
|
||||
|
||||
// Check mozIVisitInfo properties.
|
||||
do_check_eq(visit.visitId, 0);
|
||||
do_check_eq(visit.sessionId, 0);
|
||||
}
|
||||
// But they should be valid for non-embed visits.
|
||||
else {
|
||||
@@ -801,7 +713,6 @@ function test_add_visit()
|
||||
|
||||
// Check mozIVisitInfo properties.
|
||||
do_check_true(visit.visitId > 0);
|
||||
do_check_true(visit.sessionId > 0);
|
||||
}
|
||||
|
||||
// If we have had all of our callbacks, continue running tests.
|
||||
@@ -875,21 +786,6 @@ function test_properties_saved()
|
||||
do_check_eq(stmt.row.count, EXPECTED_COUNT);
|
||||
stmt.finalize();
|
||||
|
||||
// mozIVisitInfo::sessionId
|
||||
stmt = DBConn().createStatement(
|
||||
"SELECT COUNT(1) AS count " +
|
||||
"FROM moz_places h " +
|
||||
"JOIN moz_historyvisits v " +
|
||||
"ON h.id = v.place_id " +
|
||||
"WHERE h.url = :page_url " +
|
||||
"AND v.session = :session_id "
|
||||
);
|
||||
stmt.params.page_url = uri.spec;
|
||||
stmt.params.session_id = visit.sessionId;
|
||||
do_check_true(stmt.executeStep());
|
||||
do_check_eq(stmt.row.count, EXPECTED_COUNT);
|
||||
stmt.finalize();
|
||||
|
||||
// mozIPlaceInfo::title
|
||||
stmt = DBConn().createStatement(
|
||||
"SELECT COUNT(1) AS count " +
|
||||
@@ -953,7 +849,6 @@ function test_referrer_saved()
|
||||
do_check_false(yield promiseIsURIVisited(places[1].uri));
|
||||
|
||||
let resultCount = 0;
|
||||
let referrerSessionId;
|
||||
let placesResult = yield promiseUpdatePlaces(places);
|
||||
if (placesResult.errors.length > 0) {
|
||||
do_throw("Unexpected error.");
|
||||
@@ -964,11 +859,8 @@ function test_referrer_saved()
|
||||
let visit = placeInfo.visits[0];
|
||||
|
||||
// We need to insert all of our visits before we can test conditions.
|
||||
if (++resultCount != places.length) {
|
||||
referrerSessionId = visit.sessionId;
|
||||
} else {
|
||||
if (++resultCount == places.length) {
|
||||
do_check_true(places[0].uri.equals(visit.referrerURI));
|
||||
do_check_eq(visit.sessionId, referrerSessionId);
|
||||
|
||||
let stmt = DBConn().createStatement(
|
||||
"SELECT COUNT(1) AS count " +
|
||||
@@ -991,43 +883,6 @@ function test_referrer_saved()
|
||||
}
|
||||
}
|
||||
|
||||
function test_sessionId_saved()
|
||||
{
|
||||
let place = {
|
||||
uri: NetUtil.newURI(TEST_DOMAIN + "test_sessionId_saved"),
|
||||
visits: [
|
||||
new VisitInfo(),
|
||||
],
|
||||
};
|
||||
place.visits[0].sessionId = 3;
|
||||
do_check_false(yield promiseIsURIVisited(place.uri));
|
||||
|
||||
let placesResult = yield promiseUpdatePlaces(place);
|
||||
if (placesResult.errors.length > 0) {
|
||||
do_throw("Unexpected error.");
|
||||
}
|
||||
let placeInfo = placesResult.results[0];
|
||||
let uri = placeInfo.uri;
|
||||
do_check_true(yield promiseIsURIVisited(uri));
|
||||
|
||||
let visit = placeInfo.visits[0];
|
||||
do_check_eq(visit.sessionId, place.visits[0].sessionId);
|
||||
|
||||
let stmt = DBConn().createStatement(
|
||||
"SELECT COUNT(1) AS count " +
|
||||
"FROM moz_historyvisits " +
|
||||
"WHERE place_id = (SELECT id FROM moz_places WHERE url = :page_url) " +
|
||||
"AND session = :session_id "
|
||||
);
|
||||
stmt.params.page_url = uri.spec;
|
||||
stmt.params.session_id = visit.sessionId;
|
||||
do_check_true(stmt.executeStep());
|
||||
do_check_eq(stmt.row.count, 1);
|
||||
stmt.finalize();
|
||||
|
||||
yield promiseAsyncUpdates();
|
||||
}
|
||||
|
||||
function test_guid_change_saved()
|
||||
{
|
||||
// First, add a visit for it.
|
||||
@@ -1237,51 +1092,6 @@ function test_visit_notifies()
|
||||
yield promiseAsyncUpdates();
|
||||
}
|
||||
|
||||
function test_referrer_sessionId_persists()
|
||||
{
|
||||
// This test ensures that a visit that has a valid referrer also gets
|
||||
// the sessionId of the referrer.
|
||||
let referrerPlace = {
|
||||
uri: NetUtil.newURI(TEST_DOMAIN + "test_referrer_sessionId_persists_ref"),
|
||||
visits: [
|
||||
new VisitInfo(),
|
||||
],
|
||||
};
|
||||
|
||||
// First we add the referrer visit, and then the main visit with referrer
|
||||
// attached. We ensure that the sessionId is maintained across the updates.
|
||||
do_check_false(yield promiseIsURIVisited(referrerPlace.uri));
|
||||
let placesResult = yield promiseUpdatePlaces(referrerPlace);
|
||||
if (placesResult.errors.length > 0) {
|
||||
do_throw("Unexpected error.");
|
||||
}
|
||||
let placeInfo = placesResult.results[0];
|
||||
do_check_true(yield promiseIsURIVisited(referrerPlace.uri));
|
||||
|
||||
let sessionId = placeInfo.visits[0].sessionId;
|
||||
do_check_neq(sessionId, null);
|
||||
|
||||
let place = {
|
||||
uri: NetUtil.newURI(TEST_DOMAIN + "test_referrer_sessionId_persists"),
|
||||
visits: [
|
||||
new VisitInfo(),
|
||||
],
|
||||
};
|
||||
place.visits[0].referrerURI = referrerPlace.uri;
|
||||
|
||||
do_check_false(yield promiseIsURIVisited(place.uri));
|
||||
placesResult = yield promiseUpdatePlaces(place);
|
||||
if (placesResult.errors.length > 0) {
|
||||
do_throw("Unexpected error.");
|
||||
}
|
||||
placeInfo = placesResult.results[0];
|
||||
do_check_true(yield promiseIsURIVisited(place.uri));
|
||||
|
||||
do_check_eq(placeInfo.visits[0].sessionId, sessionId);
|
||||
|
||||
yield promiseAsyncUpdates();
|
||||
}
|
||||
|
||||
// test with empty mozIVisitInfoCallback object
|
||||
function test_callbacks_not_supplied()
|
||||
{
|
||||
@@ -1331,8 +1141,6 @@ function test_callbacks_not_supplied()
|
||||
test_duplicate_guid_errors,
|
||||
test_invalid_referrerURI_ignored,
|
||||
test_nonnsIURI_referrerURI_ignored,
|
||||
test_invalid_sessionId_ignored,
|
||||
test_unstored_sessionId_ignored,
|
||||
test_old_referrer_ignored,
|
||||
test_place_id_ignored,
|
||||
test_handleCompletion_called_when_complete,
|
||||
@@ -1340,13 +1148,11 @@ function test_callbacks_not_supplied()
|
||||
test_properties_saved,
|
||||
test_guid_saved,
|
||||
test_referrer_saved,
|
||||
test_sessionId_saved,
|
||||
test_guid_change_saved,
|
||||
test_title_change_saved,
|
||||
test_no_title_does_not_clear_title,
|
||||
test_title_change_notifies,
|
||||
test_visit_notifies,
|
||||
test_referrer_sessionId_persists,
|
||||
test_callbacks_not_supplied,
|
||||
].forEach(add_task);
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ add_task(function test_execute()
|
||||
var node = root.getChild(i);
|
||||
// test node properties in RESULTS_AS_VISIT
|
||||
do_check_eq(node.uri, testURI.spec);
|
||||
do_check_eq(node.type, options.RESULTS_AS_VISIT);
|
||||
do_check_eq(node.type, Ci.nsINavHistoryResultNode.RESULT_TYPE_URI);
|
||||
// TODO: change query type to RESULTS_AS_FULL_VISIT and test this
|
||||
//do_check_eq(node.transitionType, histsvc.TRANSITION_TYPED);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ add_task(function test_onVisit() {
|
||||
do_check_true(aURI.equals(testuri));
|
||||
do_check_true(aVisitID > 0);
|
||||
do_check_eq(aTime, testtime);
|
||||
do_check_true(aSessionID > 0);
|
||||
do_check_eq(aSessionID, 0);
|
||||
do_check_eq(aReferringID, 0);
|
||||
do_check_eq(aTransitionType, TRANSITION_TYPED);
|
||||
do_check_guid_for_uri(aURI, aGUID);
|
||||
@@ -82,7 +82,7 @@ add_task(function test_onVisit() {
|
||||
do_check_true(aURI.equals(testuri));
|
||||
do_check_true(aVisitID > 0);
|
||||
do_check_eq(aTime, testtime);
|
||||
do_check_true(aSessionID > 0);
|
||||
do_check_eq(aSessionID, 0);
|
||||
do_check_eq(aReferringID, 0);
|
||||
do_check_eq(aTransitionType, TRANSITION_FRAMED_LINK);
|
||||
do_check_guid_for_uri(aURI, aGUID);
|
||||
|
||||
Reference in New Issue
Block a user