author | Doug Thayer <dothayer@mozilla.com> |
Wed, 20 Dec 2017 14:27:24 -0800 | |
changeset 450375 | a542159042f5ff484b864acb4d9c61242ad49dd7 |
parent 450374 | e08b9e460de6afca511d6d03abe09b5fadff0174 |
child 450376 | f228865f492ca24b82720fc40fdb00b8b0e8c10c |
push id | 8527 |
push user | Callek@gmail.com |
push date | Thu, 11 Jan 2018 21:05:50 +0000 |
treeherder | mozilla-beta@95342d212a7a [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mak |
bugs | 1421703 |
milestone | 59.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/components/extensions/ext-history.js +++ b/browser/components/extensions/ext-history.js @@ -92,26 +92,28 @@ const convertNavHistoryContainerResultNo var _observer; const getHistoryObserver = () => { if (!_observer) { _observer = new class extends EventEmitter { onDeleteURI(uri, guid, reason) { this.emit("visitRemoved", {allHistory: false, urls: [uri.spec]}); } - onVisit(uri, visitId, time, sessionId, referringId, transitionType, guid, hidden, visitCount, typed, lastKnownTitle) { - let data = { - id: guid, - url: uri.spec, - title: lastKnownTitle || "", - lastVisitTime: time / 1000, // time from Places is microseconds, - visitCount, - typedCount: typed, - }; - this.emit("visited", data); + onVisits(visits) { + for (let visit of visits) { + let data = { + id: visit.guid, + url: visit.uri.spec, + title: visit.lastKnownTitle || "", + lastVisitTime: visit.time / 1000, // time from Places is microseconds, + visitCount: visit.visitCount, + typedCount: visit.typed, + }; + this.emit("visited", data); + } } onBeginUpdateBatch() {} onEndUpdateBatch() {} onTitleChanged(uri, title) { this.emit("titleChanged", {url: uri.spec, title: title}); } onClearHistory() { this.emit("visitRemoved", {allHistory: true, urls: []});
--- a/browser/extensions/activity-stream/lib/PlacesFeed.jsm +++ b/browser/extensions/activity-stream/lib/PlacesFeed.jsm @@ -67,17 +67,17 @@ class HistoryObserver extends Observer { */ onClearHistory() { this.dispatch({type: at.PLACES_HISTORY_CLEARED}); } // Empty functions to make xpconnect happy onBeginUpdateBatch() {} onEndUpdateBatch() {} - onVisit() {} + onVisits() {} onTitleChanged() {} onFrecencyChanged() {} onManyFrecenciesChanged() {} onPageChanged() {} onDeleteVisits() {} } /**
--- a/browser/modules/WindowsPreviewPerTab.jsm +++ b/browser/modules/WindowsPreviewPerTab.jsm @@ -838,17 +838,17 @@ this.AeroPeek = { }); break; } }, /* nsINavHistoryObserver implementation */ onBeginUpdateBatch() {}, onEndUpdateBatch() {}, - onVisit() {}, + onVisits() {}, onTitleChanged() {}, onFrecencyChanged() {}, onManyFrecenciesChanged() {}, onDeleteURI() {}, onClearHistory() {}, onDeleteVisits() {}, onPageChanged(uri, changedConst, newValue) { if (this.enabled && changedConst == Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON) {
--- a/services/sync/modules/engines/history.js +++ b/services/sync/modules/engines/history.js @@ -465,25 +465,27 @@ HistoryTracker.prototype = { onDeleteVisits(uri, visitTime, guid, reason) { this.onDeleteAffectsGUID(uri, guid, reason, "onDeleteVisits", SCORE_INCREMENT_SMALL); }, onDeleteURI(uri, guid, reason) { this.onDeleteAffectsGUID(uri, guid, reason, "onDeleteURI", SCORE_INCREMENT_XLARGE); }, - onVisit(uri, vid, time, session, referrer, trans, guid) { + onVisits(aVisits) { if (this.ignoreAll) { - this._log.trace("ignoreAll: ignoring visit for " + guid); + this._log.trace("ignoreAll: ignoring visits [" + + aVisits.map(v => v.guid).join(",") + "]"); return; } - - this._log.trace("onVisit: " + uri.spec); - if (this.engine.shouldSyncURL(uri.spec) && this.addChangedID(guid)) { - this.score += SCORE_INCREMENT_SMALL; + for (let {uri, guid} of aVisits) { + this._log.trace("onVisits: " + uri.spec); + if (this.engine.shouldSyncURL(uri.spec) && this.addChangedID(guid)) { + this.score += SCORE_INCREMENT_SMALL; + } } }, onClearHistory() { this._log.trace("onClearHistory"); // Note that we're going to trigger a sync, but none of the cleared // pages are tracked, so the deletions will not be propagated. // See Bug 578694.
--- a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm +++ b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm @@ -1023,17 +1023,17 @@ this.DownloadHistoryObserver.prototype = // nsINavHistoryObserver onClearHistory: function DL_onClearHistory() { this._list.removeFinished(); }, onTitleChanged() {}, onBeginUpdateBatch() {}, onEndUpdateBatch() {}, - onVisit() {}, + onVisits() {}, onPageChanged() {}, onDeleteVisits() {}, }; /** * This view can be added to a DownloadList object to trigger a save operation * in the given DownloadStore object when a relevant change occurs. You should * call the "initialize" method in order to register the view and load the
--- a/toolkit/components/places/History.cpp +++ b/toolkit/components/places/History.cpp @@ -164,16 +164,131 @@ struct VisitData { // Indicates whether frecency should be updated for this visit. bool shouldUpdateFrecency; // Whether this is a redirect source. bool redirect; }; //////////////////////////////////////////////////////////////////////////////// +//// nsVisitData + +class nsVisitData : public nsIVisitData +{ +public: + explicit nsVisitData(nsIURI* aURI, + int64_t aVisitId, + PRTime aTime, + int64_t aReferrerVisitId, + int32_t aTransitionType, + const nsACString& aGuid, + bool aHidden, + uint32_t aVisitCount, + uint32_t aTyped, + const nsAString& aLastKnownTitle) + : mURI(aURI) + , mVisitId(aVisitId) + , mTime(aTime) + , mReferrerVisitId(aReferrerVisitId) + , mTransitionType(aTransitionType) + , mGuid(aGuid) + , mHidden(aHidden) + , mVisitCount(aVisitCount) + , mTyped(aTyped) + , mLastKnownTitle(aLastKnownTitle) + { + MOZ_ASSERT(NS_IsMainThread(), + "nsVisitData should only be constructed on the main thread."); + } + + NS_DECL_ISUPPORTS + + NS_IMETHOD GetUri(nsIURI** aUri) override + { + NS_ENSURE_ARG_POINTER(aUri); + *aUri = mURI; + NS_IF_ADDREF(*aUri); + return NS_OK; + } + + NS_IMETHOD GetVisitId(int64_t* aVisitId) override + { + *aVisitId = mVisitId; + return NS_OK; + } + + NS_IMETHOD GetTime(PRTime* aTime) override + { + *aTime = mTime; + return NS_OK; + } + + NS_IMETHOD GetReferrerId(int64_t* aReferrerVisitId) override + { + *aReferrerVisitId = mReferrerVisitId; + return NS_OK; + } + + NS_IMETHOD GetTransitionType(uint32_t* aTransitionType) override + { + *aTransitionType = mTransitionType; + return NS_OK; + } + + NS_IMETHOD GetGuid(nsACString& aGuid) override + { + aGuid.Assign(mGuid); + return NS_OK; + } + + NS_IMETHOD GetHidden(bool* aHidden) override + { + *aHidden = mHidden; + return NS_OK; + } + + NS_IMETHOD GetVisitCount(uint32_t* aVisitCount) override + { + *aVisitCount = mVisitCount; + return NS_OK; + } + + NS_IMETHOD GetTyped(uint32_t* aTyped) override + { + *aTyped = mTyped; + return NS_OK; + } + + NS_IMETHOD GetLastKnownTitle(nsAString& aLastKnownTitle) override + { + aLastKnownTitle.Assign(mLastKnownTitle); + return NS_OK; + } + +private: + virtual ~nsVisitData() { + MOZ_ASSERT(NS_IsMainThread(), + "nsVisitData should only be destructed on the main thread."); + }; + + nsCOMPtr<nsIURI> mURI; + int64_t mVisitId; + PRTime mTime; + int64_t mReferrerVisitId; + uint32_t mTransitionType; + nsCString mGuid; + bool mHidden; + uint32_t mVisitCount; + uint32_t mTyped; + nsString mLastKnownTitle; +}; + +NS_IMPL_ISUPPORTS(nsVisitData, nsIVisitData) + +//////////////////////////////////////////////////////////////////////////////// //// RemoveVisitsFilter /** * Used to store visit filters for RemoveVisits. */ struct RemoveVisitsFilter { RemoveVisitsFilter() : transitionType(UINT32_MAX) @@ -643,56 +758,51 @@ public: , mHistory(History::GetService()) { aPlaces.SwapElements(mPlaces); } nsresult NotifyVisit(nsNavHistory* aNavHistory, nsCOMPtr<nsIObserverService>& aObsService, PRTime aNow, - nsTArray<URIParams>& aNotifyVisitedURIs, + nsIURI* aURI, const VisitData& aPlace) { - nsCOMPtr<nsIURI> uri; - MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), aPlace.spec)); - if (!uri) { - return NS_ERROR_UNEXPECTED; - } - // Notify the visit. Note that TRANSITION_EMBED visits are never added - // to the database, thus cannot be queried and we don't notify them. - if (aPlace.transitionType != nsINavHistoryService::TRANSITION_EMBED) { - aNavHistory->NotifyOnVisit(uri, aPlace.visitId, aPlace.visitTime, - aPlace.referrerVisitId, aPlace.transitionType, - aPlace.guid, aPlace.hidden, - aPlace.visitCount + 1, // Add current visit. - static_cast<uint32_t>(aPlace.typed), - aPlace.title); - } - if (aObsService) { DebugOnly<nsresult> rv = - aObsService->NotifyObservers(uri, URI_VISIT_SAVED, nullptr); + aObsService->NotifyObservers(aURI, URI_VISIT_SAVED, nullptr); NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Could not notify observers"); } if (aNow - aPlace.visitTime < RECENTLY_VISITED_URIS_MAX_AGE) { - mHistory->AppendToRecentlyVisitedURIs(uri); + mHistory->AppendToRecentlyVisitedURIs(aURI); } - mHistory->NotifyVisited(uri); + mHistory->NotifyVisited(aURI); if (aPlace.titleChanged) { - aNavHistory->NotifyTitleChange(uri, aPlace.title, aPlace.guid); + aNavHistory->NotifyTitleChange(aURI, aPlace.title, aPlace.guid); } - URIParams serialized; - SerializeURI(uri, serialized); - aNotifyVisitedURIs.AppendElement(Move(serialized)); - return NS_OK; } + void AddPlaceForNotify(const VisitData& aPlace, + nsIURI* aURI, + nsCOMArray<nsIVisitData>& aPlaces) { + if (aPlace.transitionType != nsINavHistoryService::TRANSITION_EMBED) { + nsCOMPtr<nsIVisitData> notifyPlace = new nsVisitData( + aURI, aPlace.visitId, aPlace.visitTime, + aPlace.referrerVisitId, aPlace.transitionType, + aPlace.guid, aPlace.hidden, + aPlace.visitCount + 1, // Add current visit. + static_cast<uint32_t>(aPlace.typed), + aPlace.title); + aPlaces.AppendElement(notifyPlace.forget()); + } + } + NS_IMETHOD Run() override { MOZ_ASSERT(NS_IsMainThread(), "This should be called on the main thread"); // We are in the main thread, no need to lock. if (mHistory->IsShuttingDown()) { // If we are shutting down, we cannot notify the observers. return NS_OK; @@ -702,29 +812,62 @@ public: if (!navHistory) { NS_WARNING("Trying to notify visits observers but cannot get the history service!"); return NS_OK; } nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService(); + nsCOMArray<nsIVisitData> places; + nsCOMArray<nsIURI> uris; + if (mPlaces.Length() > 0) { + for (uint32_t i = 0; i < mPlaces.Length(); ++i) { + nsCOMPtr<nsIURI> uri; + MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), mPlaces[i].spec)); + if (!uri) { + return NS_ERROR_UNEXPECTED; + } + AddPlaceForNotify(mPlaces[i], uri, places); + uris.AppendElement(uri.forget()); + } + } else { + nsCOMPtr<nsIURI> uri; + MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), mPlace.spec)); + if (!uri) { + return NS_ERROR_UNEXPECTED; + } + AddPlaceForNotify(mPlace, uri, places); + uris.AppendElement(uri.forget()); + } + if (places.Length() > 0) { + navHistory->NotifyOnVisits(places.Elements(), places.Length()); + } + PRTime now = PR_Now(); if (mPlaces.Length() > 0) { - InfallibleTArray<URIParams> uris(mPlaces.Length()); + InfallibleTArray<URIParams> serializableUris(mPlaces.Length()); for (uint32_t i = 0; i < mPlaces.Length(); ++i) { - nsresult rv = NotifyVisit(navHistory, obsService, now, uris, mPlaces[i]); + nsresult rv = NotifyVisit(navHistory, obsService, now, uris[i], mPlaces[i]); NS_ENSURE_SUCCESS(rv, rv); + + URIParams serializedUri; + SerializeURI(uris[i], serializedUri); + serializableUris.AppendElement(Move(serializedUri)); } - mHistory->NotifyVisitedParent(uris); + mHistory->NotifyVisitedParent(serializableUris); } else { - AutoTArray<URIParams, 1> uris; - nsresult rv = NotifyVisit(navHistory, obsService, now, uris, mPlace); + AutoTArray<URIParams, 1> serializableUris; + nsresult rv = NotifyVisit(navHistory, obsService, now, uris[0], mPlace); NS_ENSURE_SUCCESS(rv, rv); - mHistory->NotifyVisitedParent(uris); + + URIParams serializedUri; + SerializeURI(uris[0], serializedUri); + serializableUris.AppendElement(Move(serializedUri)); + mHistory->NotifyVisitedParent(serializableUris); } return NS_OK; } private: nsTArray<VisitData> mPlaces; VisitData mPlace; RefPtr<History> mHistory;
--- a/toolkit/components/places/nsINavHistoryService.idl +++ b/toolkit/components/places/nsINavHistoryService.idl @@ -18,16 +18,77 @@ interface nsIFile; interface nsINavHistoryContainerResultNode; interface nsINavHistoryQueryResultNode; interface nsINavHistoryQuery; interface nsINavHistoryQueryOptions; interface nsINavHistoryResult; interface nsINavHistoryBatchCallback; +/** + * This interface exists specifically for passing visit information + * in bulk to onVisits below. + */ +[scriptable, uuid(9d8df1ff-142f-4ca7-9f45-3c62a508c7e2)] +interface nsIVisitData : nsISupports +{ + /** + * URI of the visit that was just created. + */ + readonly attribute nsIURI uri; + + /** + * Id of the visit that was just created. + */ + readonly attribute long long visitId; + + /** + * Time of the visit. + */ + readonly attribute PRTime time; + + /** + * The id of the visit the user came from, defaults to 0 for no referrer. + */ + readonly attribute long long referrerId; + + /** + * One of nsINavHistory.TRANSITION_* + */ + readonly attribute unsigned long transitionType; + + /** + * The unique id associated with the page. + */ + readonly attribute ACString guid; + + /** + * Whether the visited page is marked as hidden. + */ + readonly attribute boolean hidden; + + /** + * Number of visits (included this one) for this URI. + */ + readonly attribute unsigned long visitCount; + + /** + * Whether the URI has been typed or not. + * TODO (Bug 1271801): This will become a count, rather than a boolean. + * For future compatibility, always compare it with "> 0". + */ + readonly attribute unsigned long typed; + + /** + * The last known title of the page. Might not be from the current visit, + * and might be null if it is not known. + */ + readonly attribute AString lastKnownTitle; +}; + [scriptable, uuid(91d104bb-17ef-404b-9f9a-d9ed8de6824c)] interface nsINavHistoryResultNode : nsISupports { /** * Indentifies the parent result node in the result set. This is null for * top level nodes. */ readonly attribute nsINavHistoryContainerResultNode parent; @@ -618,58 +679,26 @@ interface nsINavHistoryObserver : nsISup /** * Notifies you that we are done doing a bunch of things and you should go * ahead and update UI, etc. */ void onEndUpdateBatch(); /** - * Called everytime a URI is visited. + * Called everytime a URI is visited, or once for a batch of visits if visits were + * added in bulk. * * @note TRANSITION_EMBED visits (corresponding to images in a page, for * example) are not displayed in history results. Most observers can * ignore TRANSITION_EMBED visit notifications (which will comprise the * majority of visit notifications) to save work. - * - * @param aVisitId - * Id of the visit that was just created. - * @param aTime - * Time of the visit. - * @param aSessionId - * No longer supported and always set to 0. - * @param aReferrerVisitId - * The id of the visit the user came from, defaults to 0 for no referrer. - * @param aTransitionType - * One of nsINavHistory.TRANSITION_* - * @param aGuid - * The unique id associated with the page. - * @param aHidden - * Whether the visited page is marked as hidden. - * @param aVisitCount - * Number of visits (included this one) for this URI. - * @param aTyped - * Whether the URI has been typed or not. - * TODO (Bug 1271801): This will become a count, rather than a boolean. - * For future compatibility, always compare it with "> 0". - * @param aLastKnownTitle - * The last known title of the page. Might not be from the current visit, - * and might be null if it is not known. */ - void onVisit(in nsIURI aURI, - in long long aVisitId, - in PRTime aTime, - in long long aSessionId, - in long long aReferrerVisitId, - in unsigned long aTransitionType, - in ACString aGuid, - in boolean aHidden, - in unsigned long aVisitCount, - in unsigned long aTyped, - in AString aLastKnownTitle); + void onVisits([array, size_is(aVisitsCount)] in nsIVisitData aVisits, + in unsigned long aVisitsCount); /** * Called whenever either the "real" title or the custom title of the page * changed. BOTH TITLES ARE ALWAYS INCLUDED in this notification, even though * only one will change at a time. Often, consumers will want to display the * user title if it is available, and fall back to the page title (the one * specified in the <title> tag of the page). *
--- a/toolkit/components/places/nsLivemarkService.js +++ b/toolkit/components/places/nsLivemarkService.js @@ -409,20 +409,22 @@ LivemarkService.prototype = { onDeleteURI(aURI) { this._withLivemarksMap(livemarksMap => { for (let livemark of livemarksMap.values()) { livemark.updateURIVisitedStatus(aURI, false); } }); }, - onVisit(aURI) { + onVisits(aVisits) { this._withLivemarksMap(livemarksMap => { - for (let livemark of livemarksMap.values()) { - livemark.updateURIVisitedStatus(aURI, true); + for (let {uri} of aVisits) { + for (let livemark of livemarksMap.values()) { + livemark.updateURIVisitedStatus(uri, true); + } } }); }, // nsISupports classID: Components.ID("{dca61eb5-c7cd-4df1-b0fb-d0722baba251}"),
--- a/toolkit/components/places/nsNavBookmarks.cpp +++ b/toolkit/components/places/nsNavBookmarks.cpp @@ -3151,35 +3151,38 @@ nsNavBookmarks::OnEndUpdateBatch() NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver, OnEndUpdateBatch()); return NS_OK; } NS_IMETHODIMP -nsNavBookmarks::OnVisit(nsIURI* aURI, int64_t aVisitId, PRTime aTime, - int64_t aSessionID, int64_t aReferringID, - uint32_t aTransitionType, const nsACString& aGUID, - bool aHidden, uint32_t aVisitCount, uint32_t aTyped, - const nsAString& aLastKnownTitle) +nsNavBookmarks::OnVisits(nsIVisitData** aVisits, uint32_t aVisitsCount) { - NS_ENSURE_ARG(aURI); - - // If the page is bookmarked, notify observers for each associated bookmark. - ItemVisitData visitData; - nsresult rv = aURI->GetSpec(visitData.bookmark.url); - NS_ENSURE_SUCCESS(rv, rv); - visitData.visitId = aVisitId; - visitData.time = aTime; - visitData.transitionType = aTransitionType; - - RefPtr< AsyncGetBookmarksForURI<ItemVisitMethod, ItemVisitData> > notifier = - new AsyncGetBookmarksForURI<ItemVisitMethod, ItemVisitData>(this, &nsNavBookmarks::NotifyItemVisited, visitData); - notifier->Init(); + NS_ENSURE_ARG(aVisits); + NS_ENSURE_ARG(aVisitsCount); + + for (uint32_t i = 0; i < aVisitsCount; ++i) { + nsIVisitData* place = aVisits[i]; + nsCOMPtr<nsIURI> uri; + MOZ_ALWAYS_SUCCEEDS(place->GetUri(getter_AddRefs(uri))); + + // If the page is bookmarked, notify observers for each associated bookmark. + ItemVisitData visitData; + nsresult rv = uri->GetSpec(visitData.bookmark.url); + NS_ENSURE_SUCCESS(rv, rv); + MOZ_ALWAYS_SUCCEEDS(place->GetVisitId(&visitData.visitId)); + MOZ_ALWAYS_SUCCEEDS(place->GetTime(&visitData.time)); + MOZ_ALWAYS_SUCCEEDS(place->GetTransitionType(&visitData.transitionType)); + + RefPtr< AsyncGetBookmarksForURI<ItemVisitMethod, ItemVisitData> > notifier = + new AsyncGetBookmarksForURI<ItemVisitMethod, ItemVisitData>(this, &nsNavBookmarks::NotifyItemVisited, visitData); + notifier->Init(); + } return NS_OK; } NS_IMETHODIMP nsNavBookmarks::OnDeleteURI(nsIURI* aURI, const nsACString& aGUID, uint16_t aReason)
--- a/toolkit/components/places/nsNavBookmarks.h +++ b/toolkit/components/places/nsNavBookmarks.h @@ -110,16 +110,22 @@ public: return gBookmarksService; } typedef mozilla::places::BookmarkData BookmarkData; typedef mozilla::places::ItemVisitData ItemVisitData; typedef mozilla::places::ItemChangeData ItemChangeData; typedef mozilla::places::BookmarkStatementId BookmarkStatementId; + nsresult OnVisit(nsIURI* aURI, int64_t aVisitId, PRTime aTime, + int64_t aSessionId, int64_t aReferringId, + uint32_t aTransitionType, const nsACString& aGUID, + bool aHidden, uint32_t aVisitCount, + uint32_t aTyped, const nsAString& aLastKnownTitle); + nsresult ResultNodeForContainer(int64_t aID, nsNavHistoryQueryOptions* aOptions, nsNavHistoryResultNode** aNode); // Find all the children of a folder, using the given query and options. // For each child, a ResultNode is created and added to |children|. // The results are ordered by folder position. nsresult QueryFolderChildren(int64_t aFolderId,
--- a/toolkit/components/places/nsNavHistory.cpp +++ b/toolkit/components/places/nsNavHistory.cpp @@ -513,45 +513,37 @@ nsNavHistory::LoadPrefs() FRECENCY_PREF(mSecondBucketWeight, PREF_FREC_SECOND_BUCKET_WEIGHT); FRECENCY_PREF(mThirdBucketWeight, PREF_FREC_THIRD_BUCKET_WEIGHT); FRECENCY_PREF(mFourthBucketWeight, PREF_FREC_FOURTH_BUCKET_WEIGHT); FRECENCY_PREF(mDefaultWeight, PREF_FREC_DEFAULT_BUCKET_WEIGHT); #undef FRECENCY_PREF } - void -nsNavHistory::NotifyOnVisit(nsIURI* aURI, - int64_t aVisitId, - PRTime aTime, - int64_t aReferrerVisitId, - int32_t aTransitionType, - const nsACString& aGuid, - bool aHidden, - uint32_t aVisitCount, - uint32_t aTyped, - const nsAString& aLastKnownTitle) +nsNavHistory::NotifyOnVisits(nsIVisitData** aVisits, uint32_t aVisitsCount) { - MOZ_ASSERT(!aGuid.IsEmpty()); - MOZ_ASSERT(aVisitCount, "Should have at least 1 visit when notifying"); - // If there's no history, this visit will surely add a day. If the visit is - // added before or after the last cached day, the day count may have changed. - // Otherwise adding multiple visits in the same day should not invalidate - // the cache. + MOZ_ASSERT(aVisits, "Can't call NotifyOnVisits with a NULL aVisits"); + MOZ_ASSERT(aVisitsCount, "Should have at least 1 visit when notifying"); + if (mDaysOfHistory == 0) { mDaysOfHistory = 1; - } else if (aTime > mLastCachedEndOfDay || aTime < mLastCachedStartOfDay) { - mDaysOfHistory = -1; + } + + for (uint32_t i = 0; i < aVisitsCount; ++i) { + PRTime time; + MOZ_ALWAYS_SUCCEEDS(aVisits[i]->GetTime(&time)); + if (time > mLastCachedEndOfDay || time < mLastCachedStartOfDay) { + mDaysOfHistory = -1; + } } NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavHistoryObserver, - OnVisit(aURI, aVisitId, aTime, 0, aReferrerVisitId, - aTransitionType, aGuid, aHidden, aVisitCount, aTyped, aLastKnownTitle)); + OnVisits(aVisits, aVisitsCount)); } void nsNavHistory::NotifyTitleChange(nsIURI* aURI, const nsString& aTitle, const nsACString& aGUID) { MOZ_ASSERT(!aGUID.IsEmpty());
--- a/toolkit/components/places/nsNavHistory.h +++ b/toolkit/components/places/nsNavHistory.h @@ -432,28 +432,19 @@ public: } int32_t GetNumVisitsForFrecency() const { return mNumVisitsForFrecency; } /** - * Fires onVisit event to nsINavHistoryService observers + * Fires onVisits event to nsINavHistoryService observers */ - void NotifyOnVisit(nsIURI* aURI, - int64_t aVisitId, - PRTime aTime, - int64_t aReferrerVisitId, - int32_t aTransitionType, - const nsACString& aGuid, - bool aHidden, - uint32_t aVisitCount, - uint32_t aTyped, - const nsAString& aLastKnownTitle); + void NotifyOnVisits(nsIVisitData** aVisits, uint32_t aVisitsCount); /** * Fires onTitleChanged event to nsINavHistoryService observers */ void NotifyTitleChange(nsIURI* aURI, const nsString& title, const nsACString& aGUID);
--- a/toolkit/components/places/nsNavHistoryResult.cpp +++ b/toolkit/components/places/nsNavHistoryResult.cpp @@ -2367,24 +2367,20 @@ static nsresult setHistoryDetailsCallbac } /** * Here we need to update all copies of the URI we have with the new visit * count, and potentially add a new entry in our query. This is the most * common update operation and it is important that it be as efficient as * possible. */ -NS_IMETHODIMP +nsresult nsNavHistoryQueryResultNode::OnVisit(nsIURI* aURI, int64_t aVisitId, - PRTime aTime, int64_t aSessionId, - int64_t aReferringId, - uint32_t aTransitionType, - const nsACString& aGUID, - bool aHidden, - uint32_t* aAdded) + PRTime aTime, uint32_t aTransitionType, + bool aHidden, uint32_t* aAdded) { if (aHidden && !mOptions->IncludeHidden()) return NS_OK; nsNavHistoryResult* result = GetResult(); NS_ENSURE_STATE(result); if (result->mBatchInProgress && ++mBatchChanges > MAX_BATCH_CHANGES_BEFORE_REFRESH) { @@ -4617,34 +4613,31 @@ nsNavHistoryResult::OnItemMoved(int64_t ENUMERATE_HISTORY_OBSERVERS(OnItemMoved(aItemId, aOldParent, aOldIndex, aNewParent, aNewIndex, aItemType, aGUID, aOldParentGUID, aNewParentGUID, aSource)); return NS_OK; } -NS_IMETHODIMP +nsresult nsNavHistoryResult::OnVisit(nsIURI* aURI, int64_t aVisitId, PRTime aTime, - int64_t aSessionId, int64_t aReferringId, - uint32_t aTransitionType, const nsACString& aGUID, - bool aHidden, uint32_t aVisitCount, uint32_t aTyped, - const nsAString& aLastKnownTitle) + uint32_t aTransitionType, const nsACString& aGUID, bool aHidden, + uint32_t aVisitCount, const nsAString& aLastKnownTitle) { NS_ENSURE_ARG(aURI); // Embed visits are never shown in our views. if (aTransitionType == nsINavHistoryService::TRANSITION_EMBED) { return NS_OK; } uint32_t added = 0; - ENUMERATE_HISTORY_OBSERVERS(OnVisit(aURI, aVisitId, aTime, aSessionId, - aReferringId, aTransitionType, aGUID, + ENUMERATE_HISTORY_OBSERVERS(OnVisit(aURI, aVisitId, aTime, aTransitionType, aHidden, &added)); // When we add visits through UpdatePlaces, we don't bother telling // the world that the title 'changed' from nothing to the first title // we ever see for a history entry. Our consumers here might still // care, though, so we have to tell them - but only for the first // visit we add. For subsequent changes, updateplaces will dispatch // ontitlechanged notifications as normal. @@ -4709,16 +4702,45 @@ nsNavHistoryResult::OnVisit(nsIURI* aURI ENUMERATE_QUERY_OBSERVERS(Refresh(), mHistoryObservers, IsContainersQuery()); } return NS_OK; } NS_IMETHODIMP +nsNavHistoryResult::OnVisits(nsIVisitData** aVisits, + uint32_t aVisitsCount) { + for (uint32_t i = 0; i < aVisitsCount; ++i) { + nsIVisitData* place = aVisits[i]; + nsCOMPtr<nsIURI> uri; + MOZ_ALWAYS_SUCCEEDS(place->GetUri(getter_AddRefs(uri))); + int64_t visitId; + MOZ_ALWAYS_SUCCEEDS(place->GetVisitId(&visitId)); + PRTime time; + MOZ_ALWAYS_SUCCEEDS(place->GetTime(&time)); + uint32_t transitionType; + MOZ_ALWAYS_SUCCEEDS(place->GetTransitionType(&transitionType)); + nsCString guid; + MOZ_ALWAYS_SUCCEEDS(place->GetGuid(guid)); + bool hidden; + MOZ_ALWAYS_SUCCEEDS(place->GetHidden(&hidden)); + uint32_t visitCount; + MOZ_ALWAYS_SUCCEEDS(place->GetVisitCount(&visitCount)); + nsString lastKnownTitle; + MOZ_ALWAYS_SUCCEEDS(place->GetLastKnownTitle(lastKnownTitle)); + nsresult rv = OnVisit(uri, visitId, time, transitionType, guid, hidden, + visitCount, lastKnownTitle); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; +} + + +NS_IMETHODIMP nsNavHistoryResult::OnTitleChanged(nsIURI* aURI, const nsAString& aPageTitle, const nsACString& aGUID) { NS_ENSURE_ARG(aURI); ENUMERATE_HISTORY_OBSERVERS(OnTitleChanged(aURI, aPageTitle, aGUID)); return NS_OK;
--- a/toolkit/components/places/nsNavHistoryResult.h +++ b/toolkit/components/places/nsNavHistoryResult.h @@ -73,35 +73,23 @@ private: NS_IMETHOD OnClearHistory() __VA_ARGS__; \ NS_IMETHOD OnPageChanged(nsIURI *aURI, uint32_t aChangedAttribute, \ const nsAString &aNewValue, \ const nsACString &aGUID) __VA_ARGS__; \ NS_IMETHOD OnDeleteVisits(nsIURI* aURI, PRTime aVisitTime, \ const nsACString& aGUID, uint16_t aReason, \ uint32_t aTransitionType) __VA_ARGS__; -// The internal version has an output aAdded parameter, it is incremented by -// query nodes when the visited uri belongs to them. If no such query exists, -// the history result creates a new query node dynamically. +// The internal version is used by query nodes. #define NS_DECL_BOOKMARK_HISTORY_OBSERVER_INTERNAL \ - NS_DECL_BOOKMARK_HISTORY_OBSERVER_BASE() \ - NS_IMETHOD OnVisit(nsIURI* aURI, int64_t aVisitId, PRTime aTime, \ - int64_t aSessionId, int64_t aReferringId, \ - uint32_t aTransitionType, const nsACString& aGUID, \ - bool aHidden, uint32_t* aAdded); + NS_DECL_BOOKMARK_HISTORY_OBSERVER_BASE() // The external version is used by results. #define NS_DECL_BOOKMARK_HISTORY_OBSERVER_EXTERNAL(...) \ - NS_DECL_BOOKMARK_HISTORY_OBSERVER_BASE(__VA_ARGS__) \ - NS_IMETHOD OnVisit(nsIURI* aURI, int64_t aVisitId, PRTime aTime, \ - int64_t aSessionId, int64_t aReferringId, \ - uint32_t aTransitionType, const nsACString& aGUID, \ - bool aHidden, uint32_t aVisitCount, \ - uint32_t aTyped, const nsAString& aLastKnownTitle) \ - __VA_ARGS__; + NS_DECL_BOOKMARK_HISTORY_OBSERVER_BASE(__VA_ARGS__) // nsNavHistoryResult // // nsNavHistory creates this object and fills in mChildren (by getting // it through GetTopLevel()). Then FilledAllResults() is called to finish // object initialization. #define NS_NAVHISTORYRESULT_IID \ @@ -119,27 +107,34 @@ public: nsNavHistoryContainerResultNode* aRoot, bool aBatchInProgress, nsNavHistoryResult** result); NS_DECLARE_STATIC_IID_ACCESSOR(NS_NAVHISTORYRESULT_IID) NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_NSINAVHISTORYRESULT + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsNavHistoryResult, nsINavHistoryResult) NS_DECL_BOOKMARK_HISTORY_OBSERVER_EXTERNAL(override) - NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsNavHistoryResult, nsINavHistoryResult) + NS_IMETHOD OnVisits(nsIVisitData** aVisits, + uint32_t aVisitsCount) override; void AddHistoryObserver(nsNavHistoryQueryResultNode* aNode); void AddBookmarkFolderObserver(nsNavHistoryFolderResultNode* aNode, int64_t aFolder); void AddAllBookmarksObserver(nsNavHistoryQueryResultNode* aNode); void RemoveHistoryObserver(nsNavHistoryQueryResultNode* aNode); void RemoveBookmarkFolderObserver(nsNavHistoryFolderResultNode* aNode, int64_t aFolder); void RemoveAllBookmarksObserver(nsNavHistoryQueryResultNode* aNode); void StopObserving(); + nsresult OnVisit(nsIURI* aURI, int64_t aVisitId, PRTime aTime, + uint32_t aTransitionType, const nsACString& aGUID, + bool aHidden, uint32_t aVisitCount, + const nsAString& aLastKnownTitle); + public: // two-stage init, use NewHistoryResult to construct explicit nsNavHistoryResult(nsNavHistoryContainerResultNode* mRoot); nsresult Init(nsINavHistoryQuery** aQueries, uint32_t aQueryCount, nsNavHistoryQueryOptions *aOptions); RefPtr<nsNavHistoryContainerResultNode> mRootNode; @@ -634,16 +629,23 @@ public: NS_DECL_NSINAVHISTORYQUERYRESULTNODE bool CanExpand(); bool IsContainersQuery(); virtual nsresult OpenContainer() override; NS_DECL_BOOKMARK_HISTORY_OBSERVER_INTERNAL + + // The internal version has an output aAdded parameter, it is incremented by + // query nodes when the visited uri belongs to them. If no such query exists, + // the history result creates a new query node dynamically. + nsresult OnVisit(nsIURI* aURI, int64_t aVisitId, PRTime aTime, + uint32_t aTransitionType, bool aHidden, + uint32_t* aAdded); virtual void OnRemoving() override; public: // this constructs lazily mURI from mQueries and mOptions, call // VerifyQueriesSerialized either this or mQueries/mOptions should be valid nsresult VerifyQueriesSerialized(); // these may be constructed lazily from mURI, call VerifyQueriesParsed
--- a/toolkit/components/places/nsPlacesExpiration.js +++ b/toolkit/components/places/nsPlacesExpiration.js @@ -531,17 +531,17 @@ nsPlacesExpiration.prototype = { this._newTimer(); }, onClearHistory: function PEX_onClearHistory() { // History status is clean after a clear history. this.status = STATUS.CLEAN; }, - onVisit() {}, + onVisits() {}, onTitleChanged() {}, onDeleteURI() {}, onPageChanged() {}, onDeleteVisits() {}, // nsITimerCallback notify: function PEX_timerCallback() {
--- a/toolkit/components/thumbnails/PageThumbs.jsm +++ b/toolkit/components/thumbnails/PageThumbs.jsm @@ -827,15 +827,15 @@ var PageThumbsHistoryObserver = { onClearHistory() { PageThumbsStorage.wipe(); }, onTitleChanged() {}, onBeginUpdateBatch() {}, onEndUpdateBatch() {}, - onVisit() {}, + onVisits() {}, onPageChanged() {}, onDeleteVisits() {}, QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver, Ci.nsISupportsWeakReference]) };
--- a/toolkit/modules/NewTabUtils.jsm +++ b/toolkit/modules/NewTabUtils.jsm @@ -742,21 +742,23 @@ var PlacesProvider = { onEndUpdateBatch() { this._batchProcessingDepth -= 1; if (this._batchProcessingDepth == 0 && this._batchCalledFrecencyChanged) { this.onManyFrecenciesChanged(); this._batchCalledFrecencyChanged = false; } }, - onVisit(aURI, aVisitId, aTime, aSessionId, aReferrerVisitId, aTransitionType, - aGuid, aHidden, aVisitCount, aTyped, aLastKnownTitle) { - // For new visits, if we're not batch processing, notify for a title // update - if (!this._batchProcessingDepth && aVisitCount == 1 && aLastKnownTitle) { - this.onTitleChanged(aURI, aLastKnownTitle, aGuid); + onVisits(aVisits) { + if (!this._batchProcessingDepth) { + for (let visit of aVisits) { + if (visit.visitCount == 1 && visit.lastKnownTitle) { + this.onTitleChanged(visit.uri, visit.lastKnownTitle, visit.guid); + } + } } }, onDeleteURI: function PlacesProvider_onDeleteURI(aURI, aGUID, aReason) { // let observers remove sensetive data associated with deleted visit this._callObservers("onDeleteURI", { url: aURI.spec, });