зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 5 changesets (bug 1340498) for build bustages on SelectionChangeListener.h on a CLOSED TREE
Backed out changeset c89b86622d38 (bug 1340498) Backed out changeset b270d4a01986 (bug 1340498) Backed out changeset 8ed32495b46f (bug 1340498) Backed out changeset df9a67c58183 (bug 1340498) Backed out changeset a5977e0708ea (bug 1340498)
This commit is contained in:
Родитель
44024fd464
Коммит
fc7e217166
|
@ -94,17 +94,17 @@ const getHistoryObserver = () => {
|
|||
onDeleteURI(uri, guid, reason) {
|
||||
this.emit("visitRemoved", {allHistory: false, urls: [uri.spec]});
|
||||
}
|
||||
handlePlacesEvents(events) {
|
||||
for (let event of events) {
|
||||
let visit = {
|
||||
id: event.pageGuid,
|
||||
url: event.url,
|
||||
title: event.lastKnownTitle || "",
|
||||
lastVisitTime: event.visitTime,
|
||||
visitCount: event.visitCount,
|
||||
typedCount: event.typedCount,
|
||||
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", visit);
|
||||
this.emit("visited", data);
|
||||
}
|
||||
}
|
||||
onBeginUpdateBatch() {}
|
||||
|
@ -122,9 +122,6 @@ const getHistoryObserver = () => {
|
|||
this.emit("visitRemoved", {allHistory: false, urls: [uri.spec]});
|
||||
}
|
||||
}();
|
||||
PlacesUtils.observers.addListener(
|
||||
["page-visited"],
|
||||
_observer.handlePlacesEvents.bind(_observer));
|
||||
PlacesUtils.history.addObserver(_observer);
|
||||
}
|
||||
return _observer;
|
||||
|
|
|
@ -631,6 +631,9 @@ add_task(async function checkUndoVisitsState() {
|
|||
let observer = {
|
||||
onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch() {},
|
||||
onVisits(visits) {
|
||||
wrongMethodDeferred.reject(new Error("Unexpected call to onVisits " + visits.length));
|
||||
},
|
||||
onTitleChanged(uri) {
|
||||
wrongMethodDeferred.reject(new Error("Unexpected call to onTitleChanged " + uri.spec));
|
||||
},
|
||||
|
|
|
@ -60,6 +60,7 @@ class HistoryObserver extends Observer {
|
|||
|
||||
onEndUpdateBatch() {}
|
||||
|
||||
onVisits() {}
|
||||
|
||||
onTitleChanged() {}
|
||||
|
||||
|
|
|
@ -816,6 +816,7 @@ var AeroPeek = {
|
|||
/* nsINavHistoryObserver implementation */
|
||||
onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch() {},
|
||||
onVisits() {},
|
||||
onTitleChanged() {},
|
||||
onFrecencyChanged() {},
|
||||
onManyFrecenciesChanged() {},
|
||||
|
|
|
@ -55,6 +55,7 @@ function test() {
|
|||
var historyObserver = {
|
||||
onBeginUpdateBatch: function() {},
|
||||
onEndUpdateBatch: function() {},
|
||||
onVisits: function() {},
|
||||
onTitleChanged: function(aURI, aPageTitle) {},
|
||||
onDeleteURI: function(aURI) {},
|
||||
onClearHistory: function() {},
|
||||
|
|
|
@ -15,6 +15,7 @@ add_task(async function() {
|
|||
var historyObserver = {
|
||||
onBeginUpdateBatch: function() {},
|
||||
onEndUpdateBatch: function() {},
|
||||
onVisits: function() {},
|
||||
onTitleChanged: function(aURI, aPageTitle) {
|
||||
aURI = aURI.spec;
|
||||
switch (aURI) {
|
||||
|
|
|
@ -48,6 +48,7 @@ function test() {
|
|||
|
||||
onBeginUpdateBatch: function() { },
|
||||
onEndUpdateBatch: function() { },
|
||||
onVisits: function() { },
|
||||
onTitleChanged: function() { },
|
||||
onDeleteURI: function() { },
|
||||
onClearHistory: function() { },
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#include "mozilla/dom/PlacesEvent.h"
|
||||
|
||||
#include "mozilla/HoldDropJSObjects.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(PlacesEvent)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PlacesEvent)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PlacesEvent)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(PlacesEvent)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(PlacesEvent, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(PlacesEvent, Release)
|
||||
|
||||
already_AddRefed<PlacesEvent>
|
||||
PlacesEvent::Constructor(const GlobalObject& aGlobal,
|
||||
PlacesEventType aType,
|
||||
ErrorResult& rv)
|
||||
{
|
||||
RefPtr<PlacesEvent> event = new PlacesEvent(aType);
|
||||
return event.forget();
|
||||
}
|
||||
|
||||
nsISupports*
|
||||
PlacesEvent::GetParentObject() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
PlacesEvent::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return PlacesEventBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -1,48 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_PlacesEvent_h
|
||||
#define mozilla_dom_PlacesEvent_h
|
||||
|
||||
#include "mozilla/dom/PlacesEventBinding.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class PlacesEvent : public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
explicit PlacesEvent(PlacesEventType aType)
|
||||
: mType(aType)
|
||||
{}
|
||||
|
||||
static already_AddRefed<PlacesEvent>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
PlacesEventType aType,
|
||||
ErrorResult& aRv);
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(PlacesEvent)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(PlacesEvent)
|
||||
|
||||
nsISupports* GetParentObject() const;
|
||||
|
||||
JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
PlacesEventType Type() const { return mType; }
|
||||
|
||||
virtual const PlacesVisit* AsPlacesVisit() const { return nullptr; }
|
||||
protected:
|
||||
virtual ~PlacesEvent() = default;
|
||||
PlacesEventType mType;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_PlacesEvent_h
|
|
@ -1,350 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#include "PlacesObservers.h"
|
||||
|
||||
#include "PlacesWeakCallbackWrapper.h"
|
||||
#include "nsIWeakReferenceUtils.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
template <class T>
|
||||
struct Flagged
|
||||
{
|
||||
Flagged(uint32_t aFlags, T&& aValue)
|
||||
: flags(aFlags)
|
||||
, value(std::forward<T>(aValue))
|
||||
{}
|
||||
Flagged(Flagged&& aOther)
|
||||
: Flagged(std::move(aOther.flags), std::move(aOther.value))
|
||||
{}
|
||||
Flagged(const Flagged& aOther) = default;
|
||||
~Flagged() = default;
|
||||
|
||||
uint32_t flags;
|
||||
T value;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
using FlaggedArray = nsTArray<Flagged<T>>;
|
||||
|
||||
template <class T>
|
||||
struct ListenerCollection
|
||||
{
|
||||
static StaticAutoPtr<FlaggedArray<T>> gListeners;
|
||||
static StaticAutoPtr<FlaggedArray<T>> gListenersToRemove;
|
||||
|
||||
static FlaggedArray<T>* GetListeners() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!gListeners) {
|
||||
gListeners = new FlaggedArray<T>();
|
||||
ClearOnShutdown(&gListeners);
|
||||
}
|
||||
return gListeners;
|
||||
}
|
||||
|
||||
static FlaggedArray<T>* GetListenersToRemove() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!gListenersToRemove) {
|
||||
gListenersToRemove = new FlaggedArray<T>();
|
||||
ClearOnShutdown(&gListenersToRemove);
|
||||
}
|
||||
return gListenersToRemove;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
StaticAutoPtr<FlaggedArray<T>> ListenerCollection<T>::gListeners;
|
||||
template <class T>
|
||||
StaticAutoPtr<FlaggedArray<T>> ListenerCollection<T>::gListenersToRemove;
|
||||
|
||||
typedef ListenerCollection<RefPtr<PlacesEventCallback>> JSListeners;
|
||||
typedef ListenerCollection<WeakPtr<PlacesWeakCallbackWrapper>> WeakJSListeners;
|
||||
typedef ListenerCollection<WeakPtr<places::INativePlacesEventCallback>> WeakNativeListeners;
|
||||
|
||||
static bool gCallingListeners = false;
|
||||
|
||||
uint32_t
|
||||
GetEventTypeFlag(PlacesEventType aEventType)
|
||||
{
|
||||
if (aEventType == PlacesEventType::None) {
|
||||
return 0;
|
||||
}
|
||||
return 1 << ((uint32_t)aEventType - 1);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GetFlagsForEventTypes(const nsTArray<PlacesEventType>& aEventTypes)
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
for (PlacesEventType eventType : aEventTypes) {
|
||||
flags |= GetEventTypeFlag(eventType);
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GetFlagsForEvents(const nsTArray<OwningNonNull<PlacesEvent>>& aEvents)
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
for (const PlacesEvent& event : aEvents) {
|
||||
flags |= GetEventTypeFlag(event.Type());
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
template <class TWrapped, class TUnwrapped>
|
||||
void CallListeners(uint32_t aEventFlags,
|
||||
FlaggedArray<TWrapped>& aListeners,
|
||||
const Sequence<OwningNonNull<PlacesEvent>>& aEvents,
|
||||
const std::function<TUnwrapped(TWrapped&)>& aUnwrapListener,
|
||||
const std::function<void(TUnwrapped&, const Sequence<OwningNonNull<PlacesEvent>>&)>& aCallListener)
|
||||
{
|
||||
for (uint32_t i = 0; i < aListeners.Length(); i++) {
|
||||
Flagged<TWrapped>& l = aListeners[i];
|
||||
TUnwrapped unwrapped = aUnwrapListener(l.value);
|
||||
if (!unwrapped) {
|
||||
aListeners.RemoveElementAt(i);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((l.flags & aEventFlags) == aEventFlags) {
|
||||
aCallListener(unwrapped, aEvents);
|
||||
} else if (l.flags & aEventFlags) {
|
||||
Sequence<OwningNonNull<PlacesEvent>> filtered;
|
||||
for (const OwningNonNull<PlacesEvent>& event : aEvents) {
|
||||
if (l.flags & GetEventTypeFlag(event->Type())) {
|
||||
bool success = !!filtered.AppendElement(event, fallible);
|
||||
MOZ_RELEASE_ASSERT(success);
|
||||
}
|
||||
}
|
||||
aCallListener(unwrapped, filtered);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PlacesObservers::AddListener(GlobalObject& aGlobal,
|
||||
const nsTArray<PlacesEventType>& aEventTypes,
|
||||
PlacesEventCallback& aCallback,
|
||||
ErrorResult& rv)
|
||||
{
|
||||
uint32_t flags = GetFlagsForEventTypes(aEventTypes);
|
||||
|
||||
FlaggedArray<RefPtr<PlacesEventCallback>>* listeners =
|
||||
JSListeners::GetListeners();
|
||||
Flagged<RefPtr<PlacesEventCallback>> pair(flags, &aCallback);
|
||||
listeners->AppendElement(pair);
|
||||
}
|
||||
|
||||
void
|
||||
PlacesObservers::AddListener(GlobalObject& aGlobal,
|
||||
const nsTArray<PlacesEventType>& aEventTypes,
|
||||
PlacesWeakCallbackWrapper& aCallback,
|
||||
ErrorResult& rv)
|
||||
{
|
||||
uint32_t flags = GetFlagsForEventTypes(aEventTypes);
|
||||
|
||||
FlaggedArray<WeakPtr<PlacesWeakCallbackWrapper>>* listeners =
|
||||
WeakJSListeners::GetListeners();
|
||||
WeakPtr<PlacesWeakCallbackWrapper> weakCb(&aCallback);
|
||||
MOZ_ASSERT(weakCb.get());
|
||||
Flagged<WeakPtr<PlacesWeakCallbackWrapper>> flagged(flags, std::move(weakCb));
|
||||
listeners->AppendElement(flagged);
|
||||
}
|
||||
|
||||
void
|
||||
PlacesObservers::AddListener(const nsTArray<PlacesEventType>& aEventTypes,
|
||||
places::INativePlacesEventCallback* aCallback)
|
||||
{
|
||||
uint32_t flags = GetFlagsForEventTypes(aEventTypes);
|
||||
|
||||
FlaggedArray<WeakPtr<places::INativePlacesEventCallback>>* listeners =
|
||||
WeakNativeListeners::GetListeners();
|
||||
Flagged<WeakPtr<places::INativePlacesEventCallback>> pair(flags, aCallback);
|
||||
listeners->AppendElement(pair);
|
||||
}
|
||||
|
||||
void
|
||||
PlacesObservers::RemoveListener(GlobalObject& aGlobal,
|
||||
const nsTArray<PlacesEventType>& aEventTypes,
|
||||
PlacesEventCallback& aCallback,
|
||||
ErrorResult& rv)
|
||||
{
|
||||
uint32_t flags = GetFlagsForEventTypes(aEventTypes);
|
||||
if (gCallingListeners) {
|
||||
FlaggedArray<RefPtr<PlacesEventCallback>>* listeners =
|
||||
JSListeners::GetListenersToRemove();
|
||||
Flagged<RefPtr<PlacesEventCallback>> pair(flags, &aCallback);
|
||||
listeners->AppendElement(pair);
|
||||
} else {
|
||||
RemoveListener(flags, aCallback);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PlacesObservers::RemoveListener(GlobalObject& aGlobal,
|
||||
const nsTArray<PlacesEventType>& aEventTypes,
|
||||
PlacesWeakCallbackWrapper& aCallback,
|
||||
ErrorResult& rv)
|
||||
{
|
||||
uint32_t flags = GetFlagsForEventTypes(aEventTypes);
|
||||
if (gCallingListeners) {
|
||||
FlaggedArray<WeakPtr<PlacesWeakCallbackWrapper>>* listeners =
|
||||
WeakJSListeners::GetListenersToRemove();
|
||||
WeakPtr<PlacesWeakCallbackWrapper> weakCb(&aCallback);
|
||||
MOZ_ASSERT(weakCb.get());
|
||||
Flagged<WeakPtr<PlacesWeakCallbackWrapper>> flagged(flags, std::move(weakCb));
|
||||
listeners->AppendElement(flagged);
|
||||
} else {
|
||||
RemoveListener(flags, aCallback);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PlacesObservers::RemoveListener(const nsTArray<PlacesEventType>& aEventTypes,
|
||||
places::INativePlacesEventCallback* aCallback)
|
||||
{
|
||||
uint32_t flags = GetFlagsForEventTypes(aEventTypes);
|
||||
if (gCallingListeners) {
|
||||
FlaggedArray<WeakPtr<places::INativePlacesEventCallback>>* listeners =
|
||||
WeakNativeListeners::GetListenersToRemove();
|
||||
Flagged<WeakPtr<places::INativePlacesEventCallback>> pair(flags, aCallback);
|
||||
listeners->AppendElement(pair);
|
||||
} else {
|
||||
RemoveListener(flags, aCallback);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PlacesObservers::RemoveListener(uint32_t aFlags,
|
||||
PlacesEventCallback& aCallback)
|
||||
{
|
||||
FlaggedArray<RefPtr<PlacesEventCallback>>& listeners =
|
||||
*JSListeners::GetListeners();
|
||||
for (uint32_t i = 0; i < listeners.Length(); i++) {
|
||||
Flagged<RefPtr<PlacesEventCallback>>& l = listeners[i];
|
||||
if (!(*l.value == aCallback)) {
|
||||
continue;
|
||||
}
|
||||
if (l.flags == aFlags) {
|
||||
listeners.RemoveElementAt(i);
|
||||
i--;
|
||||
} else {
|
||||
l.flags &= ~aFlags;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PlacesObservers::RemoveListener(uint32_t aFlags,
|
||||
PlacesWeakCallbackWrapper& aCallback)
|
||||
{
|
||||
FlaggedArray<WeakPtr<PlacesWeakCallbackWrapper>>& listeners =
|
||||
*WeakJSListeners::GetListeners();
|
||||
for (uint32_t i = 0; i < listeners.Length(); i++) {
|
||||
Flagged<WeakPtr<PlacesWeakCallbackWrapper>>& l = listeners[i];
|
||||
RefPtr<PlacesWeakCallbackWrapper> unwrapped = l.value.get();
|
||||
if (unwrapped != &aCallback) {
|
||||
continue;
|
||||
}
|
||||
if (l.flags == aFlags) {
|
||||
listeners.RemoveElementAt(i);
|
||||
i--;
|
||||
} else {
|
||||
l.flags &= ~aFlags;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PlacesObservers::RemoveListener(uint32_t aFlags,
|
||||
places::INativePlacesEventCallback* aCallback)
|
||||
{
|
||||
FlaggedArray<WeakPtr<places::INativePlacesEventCallback>>& listeners =
|
||||
*WeakNativeListeners::GetListeners();
|
||||
for (uint32_t i = 0; i < listeners.Length(); i++) {
|
||||
Flagged<WeakPtr<places::INativePlacesEventCallback>>& l = listeners[i];
|
||||
RefPtr<places::INativePlacesEventCallback> unwrapped = l.value.get();
|
||||
if (unwrapped != aCallback) {
|
||||
continue;
|
||||
}
|
||||
if (l.flags == aFlags) {
|
||||
listeners.RemoveElementAt(i);
|
||||
i--;
|
||||
} else {
|
||||
l.flags &= ~aFlags;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PlacesObservers::NotifyListeners(GlobalObject& aGlobal,
|
||||
const Sequence<OwningNonNull<PlacesEvent>>& aEvents,
|
||||
ErrorResult& rv)
|
||||
{
|
||||
NotifyListeners(aEvents);
|
||||
}
|
||||
|
||||
void
|
||||
PlacesObservers::NotifyListeners(const Sequence<OwningNonNull<PlacesEvent>>& aEvents)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(!gCallingListeners);
|
||||
gCallingListeners = true;
|
||||
uint32_t flags = GetFlagsForEvents(aEvents);
|
||||
|
||||
CallListeners<RefPtr<PlacesEventCallback>, RefPtr<PlacesEventCallback>>(
|
||||
flags, *JSListeners::GetListeners(), aEvents,
|
||||
[](auto& cb) { return cb; },
|
||||
[&](auto& cb, const auto& events) {
|
||||
cb->Call(aEvents);
|
||||
});
|
||||
|
||||
CallListeners<WeakPtr<places::INativePlacesEventCallback>,
|
||||
RefPtr<places::INativePlacesEventCallback>>(
|
||||
flags, *WeakNativeListeners::GetListeners(), aEvents,
|
||||
[](auto& cb) { return cb.get(); },
|
||||
[&](auto& cb, const Sequence<OwningNonNull<PlacesEvent>>& events) {
|
||||
cb->HandlePlacesEvent(events);
|
||||
});
|
||||
|
||||
CallListeners<WeakPtr<PlacesWeakCallbackWrapper>,
|
||||
RefPtr<PlacesWeakCallbackWrapper>>(
|
||||
flags, *WeakJSListeners::GetListeners(), aEvents,
|
||||
[](auto& cb) { return cb.get(); },
|
||||
[&](auto& cb, const auto& events) {
|
||||
cb->mCallback->Call(aEvents);
|
||||
});
|
||||
|
||||
auto& listenersToRemove = *JSListeners::GetListenersToRemove();
|
||||
if (listenersToRemove.Length() > 0) {
|
||||
for (auto& listener : listenersToRemove) {
|
||||
RemoveListener(listener.flags, *listener.value);
|
||||
}
|
||||
}
|
||||
|
||||
auto& weakListenersToRemove = *WeakJSListeners::GetListenersToRemove();
|
||||
if (weakListenersToRemove.Length() > 0) {
|
||||
for (auto& listener : weakListenersToRemove) {
|
||||
RemoveListener(listener.flags, *listener.value.get());
|
||||
}
|
||||
}
|
||||
|
||||
auto& nativeListenersToRemove = *WeakNativeListeners::GetListenersToRemove();
|
||||
if (nativeListenersToRemove.Length() > 0) {
|
||||
for (auto& listener : nativeListenersToRemove) {
|
||||
RemoveListener(listener.flags, listener.value.get());
|
||||
}
|
||||
}
|
||||
|
||||
gCallingListeners = false;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -1,62 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_PlacesObservers__
|
||||
#define mozilla_dom_PlacesObservers__
|
||||
|
||||
#include "mozilla/AlreadyAddRefed.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/PlacesObserversBinding.h"
|
||||
#include "mozilla/dom/PlacesEvent.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/Pair.h"
|
||||
#include "mozilla/places/INativePlacesEventCallback.h"
|
||||
#include "nsIWeakReferenceUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
|
||||
class PlacesObservers
|
||||
{
|
||||
public:
|
||||
static void AddListener(GlobalObject& aGlobal,
|
||||
const nsTArray<PlacesEventType>& aEventTypes,
|
||||
PlacesEventCallback& aCallback,
|
||||
ErrorResult& rv);
|
||||
static void AddListener(GlobalObject& aGlobal,
|
||||
const nsTArray<PlacesEventType>& aEventTypes,
|
||||
PlacesWeakCallbackWrapper& aCallback,
|
||||
ErrorResult& rv);
|
||||
static void AddListener(const nsTArray<PlacesEventType>& aEventTypes,
|
||||
places::INativePlacesEventCallback* aCallback);
|
||||
static void RemoveListener(GlobalObject& aGlobal,
|
||||
const nsTArray<PlacesEventType>& aEventTypes,
|
||||
PlacesEventCallback& aCallback,
|
||||
ErrorResult& rv);
|
||||
static void RemoveListener(GlobalObject& aGlobal,
|
||||
const nsTArray<PlacesEventType>& aEventTypes,
|
||||
PlacesWeakCallbackWrapper& aCallback,
|
||||
ErrorResult& rv);
|
||||
static void RemoveListener(const nsTArray<PlacesEventType>& aEventTypes,
|
||||
places::INativePlacesEventCallback* aCallback);
|
||||
|
||||
static void NotifyListeners(GlobalObject& aGlobal,
|
||||
const Sequence<OwningNonNull<PlacesEvent>>& aEvents,
|
||||
ErrorResult& rv);
|
||||
|
||||
static void NotifyListeners(const Sequence<OwningNonNull<PlacesEvent>>& aEvents);
|
||||
|
||||
private:
|
||||
static void RemoveListener(uint32_t aFlags, PlacesEventCallback& aCallback);
|
||||
static void RemoveListener(uint32_t aFlags, PlacesWeakCallbackWrapper& aCallback);
|
||||
static void RemoveListener(uint32_t aFlags, places::INativePlacesEventCallback* aCallback);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_PlacesObservers__
|
|
@ -1,67 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_PlacesVisit_h
|
||||
#define mozilla_dom_PlacesVisit_h
|
||||
|
||||
#include "mozilla/dom/PlacesEvent.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class PlacesVisit final : public PlacesEvent
|
||||
{
|
||||
public:
|
||||
explicit PlacesVisit() : PlacesEvent(PlacesEventType::Page_visited) {}
|
||||
|
||||
static already_AddRefed<PlacesVisit>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
ErrorResult& aRv) {
|
||||
RefPtr<PlacesVisit> event = new PlacesVisit();
|
||||
return event.forget();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override
|
||||
{
|
||||
return PlacesVisitBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
const PlacesVisit* AsPlacesVisit() const override { return this; }
|
||||
|
||||
void GetUrl(nsString& aUrl) { aUrl = mUrl; }
|
||||
uint64_t VisitId() { return mVisitId; }
|
||||
uint64_t VisitTime() { return mVisitTime; }
|
||||
uint64_t ReferringVisitId() { return mReferringVisitId; }
|
||||
uint64_t TransitionType() { return mTransitionType; }
|
||||
void GetPageGuid(nsTString<char>& aPageGuid) { aPageGuid = mPageGuid; }
|
||||
bool Hidden() { return mHidden; }
|
||||
uint32_t VisitCount() { return mVisitCount; }
|
||||
uint32_t TypedCount() { return mTypedCount; }
|
||||
void GetLastKnownTitle(nsString& aLastKnownTitle) { aLastKnownTitle = mLastKnownTitle; }
|
||||
|
||||
// It's convenient for these to be directly available in C++, so just expose
|
||||
// them. These are generally passed around with const qualifiers anyway, so
|
||||
// it shouldn't be a problem.
|
||||
nsString mUrl;
|
||||
uint64_t mVisitId;
|
||||
uint64_t mVisitTime;
|
||||
uint64_t mReferringVisitId;
|
||||
uint32_t mTransitionType;
|
||||
nsCString mPageGuid;
|
||||
bool mHidden;
|
||||
uint32_t mVisitCount;
|
||||
uint32_t mTypedCount;
|
||||
nsString mLastKnownTitle;
|
||||
|
||||
private:
|
||||
~PlacesVisit() = default;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_PlacesVisit_h
|
|
@ -1,55 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#include "mozilla/dom/PlacesWeakCallbackWrapper.h"
|
||||
|
||||
#include "mozilla/HoldDropJSObjects.h"
|
||||
#include "mozilla/dom/ProcessGlobal.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PlacesWeakCallbackWrapper, mParent, mCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(PlacesWeakCallbackWrapper, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(PlacesWeakCallbackWrapper, Release)
|
||||
|
||||
PlacesWeakCallbackWrapper::PlacesWeakCallbackWrapper(nsISupports* aParent,
|
||||
PlacesEventCallback& aCallback)
|
||||
: mParent(do_GetWeakReference(aParent))
|
||||
, mCallback(&aCallback)
|
||||
{
|
||||
}
|
||||
|
||||
already_AddRefed<PlacesWeakCallbackWrapper>
|
||||
PlacesWeakCallbackWrapper::Constructor(const GlobalObject& aGlobal,
|
||||
PlacesEventCallback& aCallback,
|
||||
ErrorResult& rv)
|
||||
{
|
||||
nsCOMPtr<nsISupports> parent = aGlobal.GetAsSupports();
|
||||
RefPtr<PlacesWeakCallbackWrapper> wrapper =
|
||||
new PlacesWeakCallbackWrapper(parent, aCallback);
|
||||
return wrapper.forget();
|
||||
}
|
||||
|
||||
PlacesWeakCallbackWrapper::~PlacesWeakCallbackWrapper()
|
||||
{
|
||||
}
|
||||
|
||||
nsISupports*
|
||||
PlacesWeakCallbackWrapper::GetParentObject() const
|
||||
{
|
||||
nsCOMPtr<nsISupports> parent = do_QueryReferent(mParent);
|
||||
return parent;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
PlacesWeakCallbackWrapper::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return PlacesWeakCallbackWrapperBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -1,49 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_PlacesWeakCallbackWrapper_h
|
||||
#define mozilla_dom_PlacesWeakCallbackWrapper_h
|
||||
|
||||
#include "mozilla/dom/PlacesObserversBinding.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/Pair.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class PlacesWeakCallbackWrapper final : public nsWrapperCache
|
||||
, public SupportsWeakPtr<PlacesWeakCallbackWrapper>
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(PlacesWeakCallbackWrapper)
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(PlacesWeakCallbackWrapper)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(PlacesWeakCallbackWrapper)
|
||||
|
||||
explicit PlacesWeakCallbackWrapper(nsISupports* aParent,
|
||||
PlacesEventCallback& aCallback);
|
||||
|
||||
static already_AddRefed<PlacesWeakCallbackWrapper>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
PlacesEventCallback& aCallback,
|
||||
ErrorResult& rv);
|
||||
|
||||
nsISupports* GetParentObject() const;
|
||||
|
||||
JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
protected:
|
||||
friend class PlacesObservers;
|
||||
~PlacesWeakCallbackWrapper();
|
||||
nsWeakPtr mParent;
|
||||
RefPtr<PlacesEventCallback> mCallback;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_PlacesWeakCallbackWrapper_h
|
|
@ -9,11 +9,6 @@
|
|||
|
||||
#include "nsISelectionListener.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsRange;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
#include "mozilla/dom/ShadowRootBinding.h"
|
||||
#include "mozilla/dom/DocumentFragment.h"
|
||||
#include "ChildIterator.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
|
|
@ -10,12 +10,9 @@
|
|||
#include "mozilla/dom/DocumentFragment.h"
|
||||
#include "mozilla/dom/DocumentOrShadowRoot.h"
|
||||
#include "mozilla/dom/NameSpaceConstants.h"
|
||||
#include "mozilla/dom/ShadowRootBinding.h"
|
||||
#include "mozilla/ServoBindings.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIdentifierMapEntry.h"
|
||||
#include "nsStubMutationObserver.h"
|
||||
#include "nsTHashtable.h"
|
||||
|
||||
class nsAtom;
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#ifndef mozilla_dom_StyleSheetList_h
|
||||
#define mozilla_dom_StyleSheetList_h
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "mozilla/dom/DocumentOrShadowRoot.h"
|
||||
#include "nsStubMutationObserver.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include "nsIAppStartup.h"
|
||||
#include "nsToolkitCompsCID.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
|
@ -201,10 +201,6 @@ EXPORTS.mozilla.dom += [
|
|||
'NodeInfoInlines.h',
|
||||
'NodeIterator.h',
|
||||
'ParentProcessMessageManager.h',
|
||||
'PlacesEvent.h',
|
||||
'PlacesObservers.h',
|
||||
'PlacesVisit.h',
|
||||
'PlacesWeakCallbackWrapper.h',
|
||||
'Pose.h',
|
||||
'ProcessGlobal.h',
|
||||
'ProcessMessageManager.h',
|
||||
|
@ -394,13 +390,6 @@ if CONFIG['FUZZING']:
|
|||
'FuzzingFunctions.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_PLACES']:
|
||||
UNIFIED_SOURCES += [
|
||||
'PlacesEvent.cpp',
|
||||
'PlacesObservers.cpp',
|
||||
'PlacesWeakCallbackWrapper.cpp',
|
||||
]
|
||||
|
||||
# these files couldn't be in UNIFIED_SOURCES for now for reasons given below:
|
||||
SOURCES += [
|
||||
# Several conflicts with other bindings.
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using mozilla::dom::DocGroup;
|
||||
using mozilla::dom::HTMLSlotElement;
|
||||
|
||||
AutoTArray<RefPtr<nsDOMMutationObserver>, 4>*
|
||||
nsDOMMutationObserver::sScheduledMutationObservers = nullptr;
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
using mozilla::MallocSizeOf;
|
||||
using mozilla::Maybe;
|
||||
using mozilla::DOMEventTargetHelper;
|
||||
using mozilla::dom::BlobURLProtocolHandler;
|
||||
using mozilla::dom::ClientInfo;
|
||||
using mozilla::dom::ServiceWorker;
|
||||
using mozilla::dom::ServiceWorkerDescriptor;
|
||||
|
|
|
@ -90,7 +90,6 @@
|
|||
#include "nsUnicharUtils.h"
|
||||
#include "nsXBLBinding.h"
|
||||
#include "nsXBLPrototypeBinding.h"
|
||||
#include "nsWindowSizes.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "HTMLLegendElement.h"
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
StaticRefPtr<nsWindowMemoryReporter> sWindowReporter;
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
#include "nsXHTMLContentSerializer.h"
|
||||
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsElementTable.h"
|
||||
|
@ -31,6 +30,7 @@
|
|||
#include "nsStubMutationObserver.h"
|
||||
#include "nsAttrName.h"
|
||||
#include "nsComputedDOMStyle.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
enum PlacesEventType {
|
||||
"none",
|
||||
|
||||
/**
|
||||
* data: PlacesVisit. Fired whenever a page is visited.
|
||||
*/
|
||||
"page-visited",
|
||||
};
|
||||
|
||||
[ChromeOnly, Exposed=(Window,System)]
|
||||
interface PlacesEvent {
|
||||
readonly attribute PlacesEventType type;
|
||||
};
|
||||
|
||||
[ChromeOnly, Exposed=(Window,System)]
|
||||
interface PlacesVisit : PlacesEvent {
|
||||
/**
|
||||
* URL of the visit.
|
||||
*/
|
||||
readonly attribute DOMString url;
|
||||
|
||||
/**
|
||||
* Id of the visit.
|
||||
*/
|
||||
readonly attribute unsigned long long visitId;
|
||||
|
||||
/**
|
||||
* Time of the visit, in milliseconds since epoch.
|
||||
*/
|
||||
readonly attribute unsigned long long visitTime;
|
||||
|
||||
/**
|
||||
* The id of the visit the user came from, defaults to 0 for no referrer.
|
||||
*/
|
||||
readonly attribute unsigned long long referringVisitId;
|
||||
|
||||
/**
|
||||
* One of nsINavHistory.TRANSITION_*
|
||||
*/
|
||||
readonly attribute unsigned long transitionType;
|
||||
|
||||
/**
|
||||
* The unique id associated with the page.
|
||||
*/
|
||||
readonly attribute ByteString pageGuid;
|
||||
|
||||
/**
|
||||
* Whether the visited page is marked as hidden.
|
||||
*/
|
||||
readonly attribute boolean hidden;
|
||||
|
||||
/**
|
||||
* Number of visits (including this one) for this URL.
|
||||
*/
|
||||
readonly attribute unsigned long visitCount;
|
||||
|
||||
/**
|
||||
* Whether the URL 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 typedCount;
|
||||
|
||||
/**
|
||||
* 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 DOMString? lastKnownTitle;
|
||||
};
|
|
@ -1,32 +0,0 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
callback PlacesEventCallback = void (sequence<PlacesEvent> events);
|
||||
|
||||
[ChromeOnly, Exposed=(Window,System),
|
||||
Constructor(PlacesEventCallback callback)]
|
||||
interface PlacesWeakCallbackWrapper {
|
||||
};
|
||||
|
||||
// Global singleton which should handle all events for places.
|
||||
[ChromeOnly, Exposed=(Window,System)]
|
||||
namespace PlacesObservers {
|
||||
[Throws]
|
||||
void addListener(sequence<PlacesEventType> eventTypes,
|
||||
PlacesEventCallback listener);
|
||||
[Throws]
|
||||
void addListener(sequence<PlacesEventType> eventTypes,
|
||||
PlacesWeakCallbackWrapper listener);
|
||||
[Throws]
|
||||
void removeListener(sequence<PlacesEventType> eventTypes,
|
||||
PlacesEventCallback listener);
|
||||
[Throws]
|
||||
void removeListener(sequence<PlacesEventType> eventTypes,
|
||||
PlacesWeakCallbackWrapper listener);
|
||||
[Throws]
|
||||
void notifyListeners(sequence<PlacesEvent> events);
|
||||
};
|
||||
|
|
@ -46,9 +46,3 @@ WEBIDL_FILES = [
|
|||
'WebExtensionContentScript.webidl',
|
||||
'WebExtensionPolicy.webidl',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_PLACES']:
|
||||
WEBIDL_FILES += [
|
||||
'PlacesEvent.webidl',
|
||||
'PlacesObservers.webidl',
|
||||
]
|
||||
|
|
|
@ -483,17 +483,11 @@ HistoryTracker.prototype = {
|
|||
onStart() {
|
||||
this._log.info("Adding Places observer.");
|
||||
PlacesUtils.history.addObserver(this, true);
|
||||
this._placesObserver =
|
||||
new PlacesWeakCallbackWrapper(this.handlePlacesEvents.bind(this));
|
||||
PlacesObservers.addListener(["page-visited"], this._placesObserver);
|
||||
},
|
||||
|
||||
onStop() {
|
||||
this._log.info("Removing Places observer.");
|
||||
PlacesUtils.history.removeObserver(this);
|
||||
if (this._placesObserver) {
|
||||
PlacesObservers.removeListener(["page-visited"], this._placesObserver);
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: ChromeUtils.generateQI([
|
||||
|
@ -524,20 +518,19 @@ HistoryTracker.prototype = {
|
|||
);
|
||||
},
|
||||
|
||||
handlePlacesEvents(aEvents) {
|
||||
this.asyncObserver.enqueueCall(() => this._handlePlacesEvents(aEvents));
|
||||
onVisits(aVisits) {
|
||||
this.asyncObserver.enqueueCall(() => this._onVisits(aVisits));
|
||||
},
|
||||
|
||||
async _handlePlacesEvents(aEvents) {
|
||||
async _onVisits(aVisits) {
|
||||
if (this.ignoreAll) {
|
||||
this._log.trace("ignoreAll: ignoring visits [" +
|
||||
aEvents.map(v => v.guid).join(",") + "]");
|
||||
aVisits.map(v => v.guid).join(",") + "]");
|
||||
return;
|
||||
}
|
||||
for (let event of aEvents) {
|
||||
this._log.trace("'page-visited': " + event.url);
|
||||
if (this.engine.shouldSyncURL(event.url) &&
|
||||
await this.addChangedID(event.pageGuid)) {
|
||||
for (let {uri, guid} of aVisits) {
|
||||
this._log.trace("onVisits: " + uri.spec);
|
||||
if (this.engine.shouldSyncURL(uri.spec) && (await this.addChangedID(guid))) {
|
||||
this.score += SCORE_INCREMENT_SMALL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -549,18 +549,15 @@ async function serverForFoo(engine, callback) {
|
|||
async function promiseVisit(expectedType, expectedURI) {
|
||||
return new Promise(resolve => {
|
||||
function done(type, uri) {
|
||||
if (uri == expectedURI.spec && type == expectedType) {
|
||||
if (uri.equals(expectedURI) && type == expectedType) {
|
||||
PlacesUtils.history.removeObserver(observer);
|
||||
PlacesObservers.removeListener(["page-visited"],
|
||||
observer.handlePlacesEvents);
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
let observer = {
|
||||
handlePlacesEvents(events) {
|
||||
Assert.equal(events.length, 1);
|
||||
Assert.equal(events[0].type, "page-visited");
|
||||
done("added", events[0].url);
|
||||
onVisits(visits) {
|
||||
Assert.equal(visits.length, 1);
|
||||
done("added", visits[0].uri);
|
||||
},
|
||||
onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch() {},
|
||||
|
@ -568,15 +565,13 @@ async function promiseVisit(expectedType, expectedURI) {
|
|||
onFrecencyChanged() {},
|
||||
onManyFrecenciesChanged() {},
|
||||
onDeleteURI(uri) {
|
||||
done("removed", uri.spec);
|
||||
done("removed", uri);
|
||||
},
|
||||
onClearHistory() {},
|
||||
onPageChanged() {},
|
||||
onDeleteVisits() {},
|
||||
};
|
||||
PlacesUtils.history.addObserver(observer, false);
|
||||
PlacesObservers.addListener(["page-visited"],
|
||||
observer.handlePlacesEvents);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -13,11 +13,26 @@ const TIMESTAMP3 = (Date.now() - 123894) * 1000;
|
|||
|
||||
function promiseOnVisitObserved() {
|
||||
return new Promise(res => {
|
||||
let listener = new PlacesWeakCallbackWrapper((events) => {
|
||||
PlacesObservers.removeListener(["page-visited"], listener);
|
||||
res();
|
||||
});
|
||||
PlacesObservers.addListener(["page-visited"], listener);
|
||||
PlacesUtils.history.addObserver({
|
||||
onBeginUpdateBatch: function onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch: function onEndUpdateBatch() {},
|
||||
onPageChanged: function onPageChanged() {},
|
||||
onTitleChanged: function onTitleChanged() {
|
||||
},
|
||||
onVisits: function onVisits() {
|
||||
PlacesUtils.history.removeObserver(this);
|
||||
res();
|
||||
},
|
||||
onDeleteVisits: function onDeleteVisits() {},
|
||||
onPageExpired: function onPageExpired() {},
|
||||
onDeleteURI: function onDeleteURI() {},
|
||||
onClearHistory: function onClearHistory() {},
|
||||
QueryInterface: ChromeUtils.generateQI([
|
||||
Ci.nsINavHistoryObserver,
|
||||
Ci.nsINavHistoryObserver_MOZILLA_1_9_1_ADDITIONS,
|
||||
Ci.nsISupportsWeakReference
|
||||
])
|
||||
}, true);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1022,6 +1022,7 @@ this.DownloadHistoryObserver.prototype = {
|
|||
onTitleChanged() {},
|
||||
onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch() {},
|
||||
onVisits() {},
|
||||
onPageChanged() {},
|
||||
onDeleteVisits() {},
|
||||
};
|
||||
|
|
|
@ -2400,7 +2400,7 @@ add_task(async function test_history() {
|
|||
|
||||
// The history notifications should be received before the download completes.
|
||||
let [time, transitionType] = await promiseVisit;
|
||||
Assert.equal(time, download.startTime.getTime());
|
||||
Assert.equal(time, download.startTime.getTime() * 1000);
|
||||
Assert.equal(transitionType, Ci.nsINavHistoryService.TRANSITION_DOWNLOAD);
|
||||
|
||||
// Restart and complete the download after clearing history.
|
||||
|
@ -2434,7 +2434,7 @@ add_task(async function test_history_tryToKeepPartialData() {
|
|||
// The time set by nsIHelperAppService may be different than the start time in
|
||||
// the download object, thus we only check that it is a meaningful time. Note
|
||||
// that we subtract one second from the earliest time to account for rounding.
|
||||
Assert.ok(time >= beforeStartTimeMs - 1000);
|
||||
Assert.ok(time >= beforeStartTimeMs * 1000 - 1000000);
|
||||
|
||||
// Complete the download before finishing the test.
|
||||
continueResponses();
|
||||
|
|
|
@ -146,16 +146,32 @@ function promiseTimeout(aTime) {
|
|||
*/
|
||||
function promiseWaitForVisit(aUrl) {
|
||||
return new Promise(resolve => {
|
||||
function listener(aEvents) {
|
||||
Assert.equal(aEvents.length, 1);
|
||||
let event = aEvents[0];
|
||||
Assert.equal(event.type, "page-visited");
|
||||
if (event.url == aUrl) {
|
||||
PlacesObservers.removeListener(["page-visited"], listener);
|
||||
resolve([event.visitTime, event.transitionType]);
|
||||
}
|
||||
}
|
||||
PlacesObservers.addListener(["page-visited"], listener);
|
||||
|
||||
let uri = NetUtil.newURI(aUrl);
|
||||
|
||||
PlacesUtils.history.addObserver({
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsINavHistoryObserver]),
|
||||
onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch() {},
|
||||
onVisits(aVisits) {
|
||||
Assert.equal(aVisits.length, 1);
|
||||
let {
|
||||
uri: visitUri,
|
||||
time,
|
||||
transitionType,
|
||||
} = aVisits[0];
|
||||
if (visitUri.equals(uri)) {
|
||||
PlacesUtils.history.removeObserver(this);
|
||||
resolve([time, transitionType]);
|
||||
}
|
||||
},
|
||||
onTitleChanged() {},
|
||||
onDeleteURI() {},
|
||||
onClearHistory() {},
|
||||
onPageChanged() {},
|
||||
onDeleteVisits() {},
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -38,10 +38,6 @@
|
|||
#include "nsTHashtable.h"
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/PlacesObservers.h"
|
||||
#include "mozilla/dom/PlacesVisit.h"
|
||||
#include "mozilla/dom/ProcessGlobal.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
|
||||
// Initial size for the cache holding visited status observers.
|
||||
#define VISIT_OBSERVERS_INITIAL_CACHE_LENGTH 64
|
||||
|
@ -173,6 +169,121 @@ struct VisitData {
|
|||
bool useFrecencyRedirectBonus;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// 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
|
||||
|
||||
|
@ -670,28 +781,21 @@ public:
|
|||
aNavHistory->NotifyTitleChange(aURI, aPlace.title, aPlace.guid);
|
||||
}
|
||||
|
||||
aNavHistory->UpdateDaysOfHistory(aPlace.visitTime);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void AddPlaceForNotify(const VisitData& aPlace,
|
||||
nsIURI* aURI,
|
||||
Sequence<OwningNonNull<PlacesEvent>>& aEvents) {
|
||||
nsCOMArray<nsIVisitData>& aPlaces) {
|
||||
if (aPlace.transitionType != nsINavHistoryService::TRANSITION_EMBED) {
|
||||
RefPtr<PlacesVisit> vd = new PlacesVisit();
|
||||
vd->mVisitId = aPlace.visitId;
|
||||
vd->mUrl.Assign(NS_ConvertUTF8toUTF16(aPlace.spec));
|
||||
vd->mVisitTime = aPlace.visitTime / 1000;
|
||||
vd->mReferringVisitId = aPlace.referrerVisitId;
|
||||
vd->mTransitionType = aPlace.transitionType;
|
||||
vd->mPageGuid.Assign(aPlace.guid);
|
||||
vd->mHidden = aPlace.hidden;
|
||||
vd->mVisitCount = aPlace.visitCount + 1; // Add current visit
|
||||
vd->mTypedCount = static_cast<uint32_t>(aPlace.typed);
|
||||
vd->mLastKnownTitle.Assign(aPlace.title);
|
||||
bool success = !!aEvents.AppendElement(vd.forget(), fallible);
|
||||
MOZ_RELEASE_ASSERT(success);
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -714,7 +818,7 @@ public:
|
|||
nsCOMPtr<nsIObserverService> obsService =
|
||||
mozilla::services::GetObserverService();
|
||||
|
||||
Sequence<OwningNonNull<PlacesEvent>> events;
|
||||
nsCOMArray<nsIVisitData> places;
|
||||
nsCOMArray<nsIURI> uris;
|
||||
if (mPlaces.Length() > 0) {
|
||||
for (uint32_t i = 0; i < mPlaces.Length(); ++i) {
|
||||
|
@ -723,7 +827,7 @@ public:
|
|||
if (!uri) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
AddPlaceForNotify(mPlaces[i], uri, events);
|
||||
AddPlaceForNotify(mPlaces[i], uri, places);
|
||||
uris.AppendElement(uri.forget());
|
||||
}
|
||||
} else {
|
||||
|
@ -732,12 +836,11 @@ public:
|
|||
if (!uri) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
AddPlaceForNotify(mPlace, uri, events);
|
||||
AddPlaceForNotify(mPlace, uri, places);
|
||||
uris.AppendElement(uri.forget());
|
||||
}
|
||||
|
||||
if (events.Length() > 0) {
|
||||
PlacesObservers::NotifyListeners(events);
|
||||
if (places.Length() > 0) {
|
||||
navHistory->NotifyOnVisits(places.Elements(), places.Length());
|
||||
}
|
||||
|
||||
PRTime now = PR_Now();
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#ifndef mozilla_image_INativePlacesEventCallback_h
|
||||
#define mozilla_image_INativePlacesEventCallback_h
|
||||
|
||||
#include "mozilla/dom/PlacesObserversBinding.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace places {
|
||||
|
||||
class INativePlacesEventCallback : public SupportsWeakPtr<INativePlacesEventCallback>
|
||||
{
|
||||
public:
|
||||
typedef dom::Sequence<OwningNonNull<dom::PlacesEvent>> PlacesEventSequence;
|
||||
|
||||
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(INativePlacesEventCallback)
|
||||
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
|
||||
|
||||
virtual void HandlePlacesEvent(const PlacesEventSequence& aEvents) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~INativePlacesEventCallback() { }
|
||||
};
|
||||
|
||||
} // namespace places
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_image_INativePlacesEventCallback_h
|
|
@ -339,7 +339,6 @@ var PlacesUtils = {
|
|||
TOPIC_BOOKMARKS_RESTORE_FAILED: "bookmarks-restore-failed",
|
||||
|
||||
ACTION_SCHEME: "moz-action:",
|
||||
observers: PlacesObservers,
|
||||
|
||||
/**
|
||||
* GUIDs associated with virtual queries that are used for displaying the
|
||||
|
|
|
@ -29,7 +29,6 @@ if CONFIG['MOZ_PLACES']:
|
|||
EXPORTS.mozilla.places = [
|
||||
'Database.h',
|
||||
'History.h',
|
||||
'INativePlacesEventCallback.h',
|
||||
'Shutdown.h',
|
||||
]
|
||||
|
||||
|
|
|
@ -63,8 +63,6 @@ interface mozIAsyncLivemarks : nsISupports
|
|||
*/
|
||||
void reloadLivemarks([optional]in boolean aForceUpdate);
|
||||
|
||||
void handlePlacesEvents(in jsval aEvents);
|
||||
|
||||
jsval invalidateCachedLivemarks();
|
||||
};
|
||||
|
||||
|
|
|
@ -29,6 +29,67 @@ 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
|
||||
{
|
||||
|
@ -581,6 +642,18 @@ interface nsINavHistoryObserver : nsISupports
|
|||
*/
|
||||
void onEndUpdateBatch();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
|
|
|
@ -12,12 +12,8 @@ ChromeUtils.defineModuleGetter(this, "NetUtil",
|
|||
"resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "history", function() {
|
||||
let livemarks = PlacesUtils.livemarks;
|
||||
// Lazily add an history observer when it's actually needed.
|
||||
PlacesUtils.history.addObserver(livemarks, true);
|
||||
let listener = new PlacesWeakCallbackWrapper(
|
||||
livemarks.handlePlacesEvents.bind(livemarks));
|
||||
PlacesObservers.addListener(["page-visited"], listener);
|
||||
PlacesUtils.history.addObserver(PlacesUtils.livemarks, true);
|
||||
return PlacesUtils.history;
|
||||
});
|
||||
|
||||
|
@ -340,21 +336,6 @@ LivemarkService.prototype = {
|
|||
return this._invalidateCachedLivemarks();
|
||||
},
|
||||
|
||||
handlePlacesEvents(aEvents) {
|
||||
if (!aEvents) {
|
||||
throw new Components.Exception("Invalid arguments",
|
||||
Cr.NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
|
||||
this._withLivemarksMap(livemarksMap => {
|
||||
for (let event of aEvents) {
|
||||
for (let livemark of livemarksMap.values()) {
|
||||
livemark.updateURIVisitedStatus(event.url, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// nsINavBookmarkObserver
|
||||
|
||||
onBeginUpdateBatch() {},
|
||||
|
@ -431,6 +412,16 @@ LivemarkService.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
onVisits(aVisits) {
|
||||
this._withLivemarksMap(livemarksMap => {
|
||||
for (let {uri} of aVisits) {
|
||||
for (let livemark of livemarksMap.values()) {
|
||||
livemark.updateURIVisitedStatus(uri, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// nsISupports
|
||||
|
||||
classID: Components.ID("{dca61eb5-c7cd-4df1-b0fb-d0722baba251}"),
|
||||
|
@ -701,18 +692,18 @@ Livemark.prototype = {
|
|||
/**
|
||||
* Updates the visited status of nodes observing this livemark.
|
||||
*
|
||||
* @param href
|
||||
* @param aURI
|
||||
* If provided will update nodes having the given uri,
|
||||
* otherwise any node.
|
||||
* @param visitedStatus
|
||||
* @param aVisitedStatus
|
||||
* Whether the nodes should be set as visited.
|
||||
*/
|
||||
updateURIVisitedStatus(href, visitedStatus) {
|
||||
updateURIVisitedStatus(aURI, aVisitedStatus) {
|
||||
let wasVisited = false;
|
||||
for (let child of this.children) {
|
||||
if (!href || child.uri.spec == href) {
|
||||
if (!aURI || child.uri.equals(aURI)) {
|
||||
wasVisited = child.visited;
|
||||
child.visited = visitedStatus;
|
||||
child.visited = aVisitedStatus;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -720,7 +711,7 @@ Livemark.prototype = {
|
|||
if (this._nodes.has(container)) {
|
||||
let nodes = this._nodes.get(container);
|
||||
for (let node of nodes) {
|
||||
if (!href || node.uri == href) {
|
||||
if (!aURI || node.uri == aURI.spec) {
|
||||
Services.tm.dispatchToMainThread(() => {
|
||||
observer.nodeHistoryDetailsChanged(node, node.time, wasVisited);
|
||||
});
|
||||
|
@ -827,7 +818,6 @@ LivemarkLoadListener.prototype = {
|
|||
|
||||
this._livemark.children = livemarkChildren;
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
this.abort(ex);
|
||||
} finally {
|
||||
this._processor.listener = null;
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
#include "nsQueryObject.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/storage.h"
|
||||
#include "mozilla/dom/PlacesObservers.h"
|
||||
#include "mozilla/dom/PlacesVisit.h"
|
||||
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
|
@ -214,9 +212,6 @@ nsNavBookmarks::Init()
|
|||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
NS_ENSURE_STATE(history);
|
||||
history->AddObserver(this, true);
|
||||
AutoTArray<PlacesEventType, 1> events;
|
||||
events.AppendElement(PlacesEventType::Page_visited);
|
||||
PlacesObservers::AddListener(events, this);
|
||||
|
||||
// DO NOT PUT STUFF HERE that can fail. See observer comment above.
|
||||
|
||||
|
@ -2058,28 +2053,30 @@ nsNavBookmarks::OnEndUpdateBatch()
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
nsNavBookmarks::HandlePlacesEvent(const PlacesEventSequence& aEvents)
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::OnVisits(nsIVisitData** aVisits, uint32_t aVisitsCount)
|
||||
{
|
||||
for (const auto& event : aEvents) {
|
||||
if (NS_WARN_IF(event->Type() != PlacesEventType::Page_visited)) {
|
||||
continue;
|
||||
}
|
||||
NS_ENSURE_ARG(aVisits);
|
||||
NS_ENSURE_ARG(aVisitsCount);
|
||||
|
||||
const dom::PlacesVisit* visit = event->AsPlacesVisit();
|
||||
if (NS_WARN_IF(!visit)) {
|
||||
continue;
|
||||
}
|
||||
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;
|
||||
visitData.visitId = visit->mVisitId;
|
||||
visitData.bookmark.url = NS_ConvertUTF16toUTF8(visit->mUrl);
|
||||
visitData.time = visit->mVisitTime * 1000;
|
||||
visitData.transitionType = visit->mTransitionType;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -78,7 +78,6 @@ class nsNavBookmarks final : public nsINavBookmarksService
|
|||
, public nsINavHistoryObserver
|
||||
, public nsIObserver
|
||||
, public nsSupportsWeakReference
|
||||
, public mozilla::places::INativePlacesEventCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -208,16 +207,6 @@ public:
|
|||
*/
|
||||
void NotifyItemChanged(const ItemChangeData& aData);
|
||||
|
||||
|
||||
/**
|
||||
* Part of INativePlacesEventCallback - handles events from the places
|
||||
* observer system.
|
||||
* @param aCx
|
||||
* A JSContext for extracting the values from aEvents.
|
||||
* @param aEvents
|
||||
* An array of weakly typed events detailing what changed.
|
||||
*/
|
||||
void HandlePlacesEvent(const PlacesEventSequence& aEvents) override;
|
||||
static const int32_t kGetChildrenIndex_Guid;
|
||||
static const int32_t kGetChildrenIndex_Position;
|
||||
static const int32_t kGetChildrenIndex_Type;
|
||||
|
|
|
@ -521,15 +521,25 @@ nsNavHistory::LoadPrefs()
|
|||
}
|
||||
|
||||
void
|
||||
nsNavHistory::UpdateDaysOfHistory(PRTime visitTime)
|
||||
nsNavHistory::NotifyOnVisits(nsIVisitData** aVisits, uint32_t aVisitsCount)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (visitTime > mLastCachedEndOfDay || visitTime < 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, mObservers, nsINavHistoryObserver,
|
||||
OnVisits(aVisits, aVisitsCount));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -435,10 +435,9 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Updates and invalidates the mDaysOfHistory cache. Should be
|
||||
* called whenever a visit is added.
|
||||
* Fires onVisits event to nsINavHistoryService observers
|
||||
*/
|
||||
void UpdateDaysOfHistory(PRTime visitTime);
|
||||
void NotifyOnVisits(nsIVisitData** aVisits, uint32_t aVisitsCount);
|
||||
|
||||
/**
|
||||
* Fires onTitleChanged event to nsINavHistoryService observers
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
#include "nsUnicharUtils.h"
|
||||
#include "prtime.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "mozilla/dom/PlacesObservers.h"
|
||||
#include "mozilla/dom/PlacesVisit.h"
|
||||
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
|
@ -3997,9 +3995,6 @@ nsNavHistoryResult::StopObserving()
|
|||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
if (history) {
|
||||
history->RemoveObserver(this);
|
||||
AutoTArray<PlacesEventType, 1> events;
|
||||
events.AppendElement(PlacesEventType::Page_visited);
|
||||
PlacesObservers::RemoveListener(events, this);
|
||||
mIsHistoryObserver = false;
|
||||
}
|
||||
}
|
||||
|
@ -4012,9 +4007,6 @@ nsNavHistoryResult::AddHistoryObserver(nsNavHistoryQueryResultNode* aNode)
|
|||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
NS_ASSERTION(history, "Can't create history service");
|
||||
history->AddObserver(this, true);
|
||||
AutoTArray<PlacesEventType, 1> events;
|
||||
events.AppendElement(PlacesEventType::Page_visited);
|
||||
PlacesObservers::AddListener(events, this);
|
||||
mIsHistoryObserver = true;
|
||||
}
|
||||
// Don't add duplicate observers. In some case we don't unregister when
|
||||
|
@ -4598,27 +4590,32 @@ nsNavHistoryResult::OnVisit(nsIURI* aURI, int64_t aVisitId, PRTime aTime,
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
nsNavHistoryResult::HandlePlacesEvent(const PlacesEventSequence& aEvents) {
|
||||
for (const auto& event : aEvents) {
|
||||
if (NS_WARN_IF(event->Type() != PlacesEventType::Page_visited)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const dom::PlacesVisit* visit = event->AsPlacesVisit();
|
||||
if (NS_WARN_IF(!visit)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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(NS_NewURI(getter_AddRefs(uri), visit->mUrl));
|
||||
if (!uri) {
|
||||
return;
|
||||
}
|
||||
OnVisit(uri, visit->mVisitId, visit->mVisitTime * 1000,
|
||||
visit->mTransitionType, visit->mPageGuid,
|
||||
visit->mHidden, visit->mVisitCount, visit->mLastKnownTitle);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#ifndef nsNavHistoryResult_h_
|
||||
#define nsNavHistoryResult_h_
|
||||
|
||||
#include "INativePlacesEventCallback.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
@ -99,8 +98,7 @@ private:
|
|||
class nsNavHistoryResult final : public nsSupportsWeakReference,
|
||||
public nsINavHistoryResult,
|
||||
public nsINavBookmarkObserver,
|
||||
public nsINavHistoryObserver,
|
||||
public mozilla::places::INativePlacesEventCallback
|
||||
public nsINavHistoryObserver
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_NAVHISTORYRESULT_IID)
|
||||
|
@ -109,6 +107,8 @@ public:
|
|||
NS_DECL_NSINAVHISTORYRESULT
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsNavHistoryResult, nsINavHistoryResult)
|
||||
NS_DECL_BOOKMARK_HISTORY_OBSERVER_EXTERNAL(override)
|
||||
NS_IMETHOD OnVisits(nsIVisitData** aVisits,
|
||||
uint32_t aVisitsCount) override;
|
||||
|
||||
void AddHistoryObserver(nsNavHistoryQueryResultNode* aNode);
|
||||
void AddBookmarkFolderObserver(nsNavHistoryFolderResultNode* aNode, int64_t aFolder);
|
||||
|
@ -174,8 +174,6 @@ public:
|
|||
ContainerObserverList mRefreshParticipants;
|
||||
void requestRefresh(nsNavHistoryContainerResultNode* aContainer);
|
||||
|
||||
void HandlePlacesEvent(const PlacesEventSequence& aEvents) override;
|
||||
|
||||
void OnMobilePrefChanged();
|
||||
|
||||
static void OnMobilePrefChangedCallback(const char* prefName, void* closure);
|
||||
|
|
|
@ -536,6 +536,7 @@ nsPlacesExpiration.prototype = {
|
|||
this.status = STATUS.CLEAN;
|
||||
},
|
||||
|
||||
onVisits() {},
|
||||
onTitleChanged() {},
|
||||
onDeleteURI() {},
|
||||
onPageChanged() {},
|
||||
|
|
|
@ -318,18 +318,6 @@ var PlacesTestUtils = Object.freeze({
|
|||
},
|
||||
|
||||
waitForNotification(notification, conditionFn = () => true, type = "bookmarks") {
|
||||
if (type == "places") {
|
||||
return new Promise(resolve => {
|
||||
function listener(events) {
|
||||
if (conditionFn(events)) {
|
||||
PlacesObservers.removeListener([notification], listener);
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
PlacesObservers.addListener([notification], listener);
|
||||
});
|
||||
}
|
||||
|
||||
let iface = type == "bookmarks" ? Ci.nsINavBookmarkObserver
|
||||
: Ci.nsINavHistoryObserver;
|
||||
return new Promise(resolve => {
|
||||
|
|
|
@ -15,33 +15,43 @@ add_task(async function() {
|
|||
];
|
||||
|
||||
// Create and add history observer.
|
||||
let count = 0;
|
||||
let expectedURI = null;
|
||||
function onVisitsListener(aEvents) {
|
||||
for (let event of aEvents) {
|
||||
info("Received onVisits: " + event.url);
|
||||
if (event.url == expectedURI) {
|
||||
count++;
|
||||
let historyObserver = {
|
||||
count: 0,
|
||||
expectedURI: null,
|
||||
onVisits(aVisits) {
|
||||
for (let {uri} of aVisits) {
|
||||
info("Received onVisits: " + uri.spec);
|
||||
if (uri.equals(this.expectedURI)) {
|
||||
this.count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch() {},
|
||||
onTitleChanged() {},
|
||||
onDeleteURI() {},
|
||||
onClearHistory() {},
|
||||
onPageChanged() {},
|
||||
onDeleteVisits() {},
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsINavHistoryObserver])
|
||||
};
|
||||
|
||||
async function promiseLoadedThreeTimes(uri) {
|
||||
count = 0;
|
||||
expectedURI = uri;
|
||||
historyObserver.count = 0;
|
||||
historyObserver.expectedURI = Services.io.newURI(uri);
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
|
||||
PlacesObservers.addListener(["page-visited"], onVisitsListener);
|
||||
PlacesUtils.history.addObserver(historyObserver);
|
||||
gBrowser.loadURI(uri);
|
||||
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, uri);
|
||||
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, uri);
|
||||
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, uri);
|
||||
PlacesObservers.removeListener(["page-visited"], onVisitsListener);
|
||||
PlacesUtils.history.removeObserver(historyObserver);
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
}
|
||||
|
||||
for (let uri of URIS) {
|
||||
await promiseLoadedThreeTimes(uri);
|
||||
is(count, 1,
|
||||
"'page-visited' has been received right number of times for " + uri);
|
||||
is(historyObserver.count, 1,
|
||||
"onVisit has been received right number of times for " + uri);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -23,6 +23,7 @@ add_task(async function() {
|
|||
|
||||
onBeginUpdateBatch() { },
|
||||
onEndUpdateBatch() { },
|
||||
onVisits() { },
|
||||
onDeleteURI() { },
|
||||
onClearHistory() { },
|
||||
onPageChanged() { },
|
||||
|
|
|
@ -11,18 +11,19 @@ add_task(async function() {
|
|||
const FINAL_URI = NetUtil.newURI(BASE_URL + "final.html");
|
||||
|
||||
let promiseVisits = new Promise(resolve => {
|
||||
let observer = {
|
||||
PlacesUtils.history.addObserver({
|
||||
__proto__: NavHistoryObserver.prototype,
|
||||
_notified: [],
|
||||
onVisit(uri, id, time, referrerId, transition) {
|
||||
info("Received onVisit: " + uri);
|
||||
info("Received onVisit: " + uri.spec);
|
||||
this._notified.push(uri);
|
||||
|
||||
if (uri != FINAL_URI.spec) {
|
||||
if (!uri.equals(FINAL_URI)) {
|
||||
return;
|
||||
}
|
||||
|
||||
is(this._notified.length, 4);
|
||||
PlacesObservers.removeListener(["page-visited"], this.handleEvents);
|
||||
PlacesUtils.history.removeObserver(this);
|
||||
|
||||
(async function() {
|
||||
// Get all pages visited from the original typed one
|
||||
|
@ -44,21 +45,18 @@ add_task(async function() {
|
|||
resolve();
|
||||
})();
|
||||
},
|
||||
handleEvents(events) {
|
||||
is(events.length, 1, "Right number of visits notified");
|
||||
is(events[0].type, "page-visited");
|
||||
onVisits(visits) {
|
||||
is(visits.length, 1, "Right number of visits notified");
|
||||
let {
|
||||
url,
|
||||
uri,
|
||||
visitId,
|
||||
visitTime,
|
||||
referringVisitId,
|
||||
time,
|
||||
referrerId,
|
||||
transitionType,
|
||||
} = events[0];
|
||||
this.onVisit(url, visitId, visitTime, referringVisitId, transitionType);
|
||||
} = visits[0];
|
||||
this.onVisit(uri, visitId, time, referrerId, transitionType);
|
||||
}
|
||||
};
|
||||
observer.handleEvents = observer.handleEvents.bind(observer);
|
||||
PlacesObservers.addListener(["page-visited"], observer.handleEvents);
|
||||
});
|
||||
});
|
||||
|
||||
PlacesUtils.history.markPageAsTyped(TEST_URI);
|
||||
|
|
|
@ -32,15 +32,15 @@ async function check_uri(uri, frecency, hidden) {
|
|||
|
||||
async function waitVisitedNotifications() {
|
||||
let redirectNotified = false;
|
||||
await PlacesTestUtils.waitForNotification("page-visited", visits => {
|
||||
await PlacesTestUtils.waitForNotification("onVisits", visits => {
|
||||
is(visits.length, 1, "Was notified for the right number of visits.");
|
||||
let {url} = visits[0];
|
||||
info("Received 'page-visited': " + url);
|
||||
if (url == REDIRECT_URI.spec) {
|
||||
let {uri} = visits[0];
|
||||
info("Received onVisits: " + uri.spec);
|
||||
if (uri.equals(REDIRECT_URI)) {
|
||||
redirectNotified = true;
|
||||
}
|
||||
return url == TARGET_URI.spec;
|
||||
}, "places");
|
||||
return uri.equals(TARGET_URI);
|
||||
}, "history");
|
||||
return redirectNotified;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,24 +10,42 @@ add_task(async function() {
|
|||
|
||||
// Create and add history observer.
|
||||
let visitedPromise = new Promise(resolve => {
|
||||
function listener(aEvents) {
|
||||
is(aEvents.length, 1, "Right number of visits notified");
|
||||
is(aEvents[0].type, "page-visited");
|
||||
let uri = NetUtil.newURI(aEvents[0].url);
|
||||
PlacesObservers.removeListener(["page-visited"], listener);
|
||||
info("Received 'page-visited': " + uri.spec);
|
||||
fieldForUrl(uri, "frecency", function(aFrecency) {
|
||||
is(aFrecency, 0, "Frecency should be 0");
|
||||
fieldForUrl(uri, "hidden", function(aHidden) {
|
||||
is(aHidden, 0, "Page should not be hidden");
|
||||
fieldForUrl(uri, "typed", function(aTyped) {
|
||||
is(aTyped, 0, "page should not be marked as typed");
|
||||
resolve();
|
||||
let historyObserver = {
|
||||
onVisit(aURI, aVisitID, aTime, aReferringID, aTransitionType) {
|
||||
PlacesUtils.history.removeObserver(historyObserver);
|
||||
info("Received onVisit: " + aURI.spec);
|
||||
fieldForUrl(aURI, "frecency", function(aFrecency) {
|
||||
is(aFrecency, 0, "Frecency should be 0");
|
||||
fieldForUrl(aURI, "hidden", function(aHidden) {
|
||||
is(aHidden, 0, "Page should not be hidden");
|
||||
fieldForUrl(aURI, "typed", function(aTyped) {
|
||||
is(aTyped, 0, "page should not be marked as typed");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
PlacesObservers.addListener(["page-visited"], listener);
|
||||
},
|
||||
onVisits(aVisits) {
|
||||
is(aVisits.length, 1, "Right number of visits notified");
|
||||
let {
|
||||
uri,
|
||||
visitId,
|
||||
time,
|
||||
referrerId,
|
||||
transitionType,
|
||||
} = aVisits[0];
|
||||
this.onVisit(uri, visitId, time, referrerId, transitionType);
|
||||
},
|
||||
onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch() {},
|
||||
onTitleChanged() {},
|
||||
onDeleteURI() {},
|
||||
onClearHistory() {},
|
||||
onPageChanged() {},
|
||||
onDeleteVisits() {},
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsINavHistoryObserver])
|
||||
};
|
||||
PlacesUtils.history.addObserver(historyObserver);
|
||||
});
|
||||
|
||||
let newTabPromise = BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
|
||||
|
|
|
@ -3,20 +3,19 @@ const TEST_PATH = getRootDirectory(gTestPath).replace("chrome://mochitests/conte
|
|||
add_task(async function checkTitleNotificationForNavigation() {
|
||||
const EXPECTED_URL = Services.io.newURI(TEST_PATH + "empty_page.html");
|
||||
let promiseTitleChanged = new Promise(resolve => {
|
||||
function onVisits(aEvents) {
|
||||
Assert.equal(aEvents.length, 1, "Right number of visits notified");
|
||||
Assert.equal(aEvents[0].type, "page-visited");
|
||||
let {
|
||||
url,
|
||||
lastKnownTitle,
|
||||
} = aEvents[0];
|
||||
info("'page-visited': " + url);
|
||||
if (url == EXPECTED_URL.spec) {
|
||||
Assert.equal(lastKnownTitle, null, "Should not have a title");
|
||||
}
|
||||
PlacesObservers.removeListener(["page-visited"], onVisits);
|
||||
}
|
||||
let obs = {
|
||||
onVisits(aVisits) {
|
||||
Assert.equal(aVisits.length, 1, "Right number of visits notified");
|
||||
let {
|
||||
uri,
|
||||
lastKnownTitle,
|
||||
} = aVisits[0];
|
||||
info("onVisits: " + uri.spec);
|
||||
if (uri.equals(EXPECTED_URL)) {
|
||||
Assert.equal(lastKnownTitle, null, "Should not have a title");
|
||||
}
|
||||
},
|
||||
|
||||
onTitleChanged(aURI, aTitle, aGuid) {
|
||||
if (aURI.equals(EXPECTED_URL)) {
|
||||
is(aTitle, "I am an empty page", "Should have correct title in titlechanged notification");
|
||||
|
@ -26,7 +25,6 @@ add_task(async function checkTitleNotificationForNavigation() {
|
|||
},
|
||||
};
|
||||
PlacesUtils.history.addObserver(obs);
|
||||
PlacesObservers.addListener(["page-visited"], onVisits);
|
||||
});
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, EXPECTED_URL.spec);
|
||||
await promiseTitleChanged;
|
||||
|
|
|
@ -39,15 +39,15 @@ add_task(async function redirect_check_new_typed_visit() {
|
|||
redirectTargetFrecency += TYPED_VISIT_BONUS;
|
||||
let redirectNotified = false;
|
||||
|
||||
let visitedPromise = PlacesTestUtils.waitForNotification("page-visited", visits => {
|
||||
let visitedPromise = PlacesTestUtils.waitForNotification("onVisits", visits => {
|
||||
is(visits.length, 1, "Was notified for the right number of visits.");
|
||||
let {url} = visits[0];
|
||||
info("Received 'page-visited': " + url);
|
||||
if (url == REDIRECT_URI.spec) {
|
||||
let {uri} = visits[0];
|
||||
info("Received onVisits for: " + uri.spec);
|
||||
if (uri.equals(REDIRECT_URI)) {
|
||||
redirectNotified = true;
|
||||
}
|
||||
return url == TARGET_URI.spec;
|
||||
}, "places");
|
||||
return uri.equals(TARGET_URI);
|
||||
}, "history");
|
||||
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, REDIRECT_URI.spec);
|
||||
info("Waiting for onVisits");
|
||||
|
@ -68,15 +68,15 @@ add_task(async function redirect_check_second_typed_visit() {
|
|||
redirectTargetFrecency += TYPED_VISIT_BONUS;
|
||||
let redirectNotified = false;
|
||||
|
||||
let visitedPromise = PlacesTestUtils.waitForNotification("page-visited", visits => {
|
||||
let visitedPromise = PlacesTestUtils.waitForNotification("onVisits", visits => {
|
||||
is(visits.length, 1, "Was notified for the right number of visits.");
|
||||
let {url} = visits[0];
|
||||
info("Received 'page-visited': " + url);
|
||||
if (url == REDIRECT_URI.spec) {
|
||||
let {uri} = visits[0];
|
||||
info("Received onVisits: " + uri.spec);
|
||||
if (uri.equals(REDIRECT_URI)) {
|
||||
redirectNotified = true;
|
||||
}
|
||||
return url == TARGET_URI.spec;
|
||||
}, "places");
|
||||
return uri.equals(TARGET_URI);
|
||||
}, "history");
|
||||
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, REDIRECT_URI.spec);
|
||||
info("Waiting for onVisits");
|
||||
|
@ -95,15 +95,15 @@ add_task(async function redirect_check_subsequent_link_visit() {
|
|||
redirectTargetFrecency += LINK_VISIT_BONUS;
|
||||
let redirectNotified = false;
|
||||
|
||||
let visitedPromise = PlacesTestUtils.waitForNotification("page-visited", visits => {
|
||||
let visitedPromise = PlacesTestUtils.waitForNotification("onVisits", visits => {
|
||||
is(visits.length, 1, "Was notified for the right number of visits.");
|
||||
let {url} = visits[0];
|
||||
info("Received 'page-visited': " + url);
|
||||
if (url == REDIRECT_URI.spec) {
|
||||
let {uri} = visits[0];
|
||||
info("Received onVisits: " + uri.spec);
|
||||
if (uri.equals(REDIRECT_URI)) {
|
||||
redirectNotified = true;
|
||||
}
|
||||
return url == TARGET_URI.spec;
|
||||
}, "places");
|
||||
return uri.equals(TARGET_URI);
|
||||
}, "history");
|
||||
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, REDIRECT_URI.spec);
|
||||
info("Waiting for onVisits");
|
||||
|
|
|
@ -25,6 +25,7 @@ add_task(async function() {
|
|||
data: [],
|
||||
onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch() {},
|
||||
onVisits() {},
|
||||
onTitleChanged(aURI, aPageTitle, aGUID) {
|
||||
this.data.push({ uri: aURI, title: aPageTitle, guid: aGUID });
|
||||
|
||||
|
|
|
@ -20,14 +20,16 @@ add_task(async function test() {
|
|||
PlacesUtils.history.markPageAsTyped(NetUtil.newURI(TEST_URL));
|
||||
|
||||
let promiseVisit = new Promise(resolve => {
|
||||
function onVisits(events) {
|
||||
PlacesObservers.removeListener(["page-visited"], onVisits);
|
||||
is(events.length, 1, "Right number of visits");
|
||||
is(events[0].type, "page-visited");
|
||||
is(events[0].url, TEST_URL, "Check visited url");
|
||||
resolve();
|
||||
}
|
||||
PlacesObservers.addListener(["page-visited"], onVisits);
|
||||
let historyObserver = {
|
||||
__proto__: NavHistoryObserver.prototype,
|
||||
onVisits(visits) {
|
||||
PlacesUtils.history.removeObserver(historyObserver);
|
||||
is(visits.length, 1, "Right number of visits");
|
||||
is(visits[0].uri.spec, TEST_URL, "Check visited url");
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
PlacesUtils.history.addObserver(historyObserver);
|
||||
});
|
||||
gBrowser.selectedBrowser.loadURI(TEST_URL);
|
||||
await promiseVisit;
|
||||
|
|
|
@ -77,6 +77,7 @@ function NavHistoryObserver() {}
|
|||
NavHistoryObserver.prototype = {
|
||||
onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch() {},
|
||||
onVisits() {},
|
||||
onTitleChanged() {},
|
||||
onDeleteURI() {},
|
||||
onClearHistory() {},
|
||||
|
|
|
@ -77,6 +77,7 @@ add_task(async function test_notifications_onDeleteURI() {
|
|||
onBeginUpdateBatch: function PEX_onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch: function PEX_onEndUpdateBatch() {},
|
||||
onClearHistory() {},
|
||||
onVisits() {},
|
||||
onTitleChanged() {},
|
||||
onDeleteURI(aURI, aGUID, aReason) {
|
||||
currentTest.receivedNotifications++;
|
||||
|
|
|
@ -102,6 +102,7 @@ add_task(async function test_notifications_onDeleteVisits() {
|
|||
onBeginUpdateBatch: function PEX_onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch: function PEX_onEndUpdateBatch() {},
|
||||
onClearHistory() {},
|
||||
onVisits() {},
|
||||
onTitleChanged() {},
|
||||
onDeleteURI(aURI, aGUID, aReason) {
|
||||
// Check this uri was not bookmarked.
|
||||
|
|
|
@ -734,6 +734,7 @@ function NavHistoryObserver() {}
|
|||
NavHistoryObserver.prototype = {
|
||||
onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch() {},
|
||||
onVisits() {},
|
||||
onTitleChanged() {},
|
||||
onDeleteURI() {},
|
||||
onClearHistory() {},
|
||||
|
|
|
@ -80,47 +80,48 @@ TitleChangedObserver.prototype = {
|
|||
|
||||
/**
|
||||
* Listens for a visit notification, and calls aCallback when it gets it.
|
||||
*
|
||||
* @param aURI
|
||||
* The URI of the page we expect a notification for.
|
||||
* @param aCallback
|
||||
* The method to call when we have gotten the proper notification about
|
||||
* being visited.
|
||||
*/
|
||||
class VisitObserver {
|
||||
constructor(aURI,
|
||||
aGUID,
|
||||
aCallback) {
|
||||
this.uri = aURI;
|
||||
this.guid = aGUID;
|
||||
this.callback = aCallback;
|
||||
this.handlePlacesEvent = this.handlePlacesEvent.bind(this);
|
||||
PlacesObservers.addListener(["page-visited"], this.handlePlacesEvent);
|
||||
}
|
||||
|
||||
handlePlacesEvent(aEvents) {
|
||||
info("'page-visited'!!!");
|
||||
Assert.equal(aEvents.length, 1, "Right number of visits notified");
|
||||
Assert.equal(aEvents[0].type, "page-visited");
|
||||
function VisitObserver(aURI,
|
||||
aGUID,
|
||||
aCallback) {
|
||||
this.uri = aURI;
|
||||
this.guid = aGUID;
|
||||
this.callback = aCallback;
|
||||
}
|
||||
VisitObserver.prototype = {
|
||||
__proto__: NavHistoryObserver.prototype,
|
||||
onVisits(aVisits) {
|
||||
info("onVisits()!!!");
|
||||
Assert.equal(aVisits.length, 1, "Right number of visits notified");
|
||||
let {
|
||||
url,
|
||||
uri,
|
||||
visitId,
|
||||
visitTime,
|
||||
referringVisitId,
|
||||
time,
|
||||
referrerId,
|
||||
transitionType,
|
||||
pageGuid,
|
||||
guid,
|
||||
hidden,
|
||||
visitCount,
|
||||
typedCount,
|
||||
typed,
|
||||
lastKnownTitle,
|
||||
} = aEvents[0];
|
||||
} = aVisits[0];
|
||||
let args = [
|
||||
visitId, visitTime, referringVisitId, transitionType, pageGuid,
|
||||
hidden, visitCount, typedCount, lastKnownTitle,
|
||||
visitId, time, referrerId, transitionType, guid,
|
||||
hidden, visitCount, typed, lastKnownTitle,
|
||||
];
|
||||
info("'page-visited' (" + url + args.join(", ") + ")");
|
||||
if (this.uri.spec != url || this.guid != pageGuid) {
|
||||
info("onVisit(" + uri.spec + args.join(", ") + ")");
|
||||
if (!this.uri.equals(uri) || this.guid != guid) {
|
||||
return;
|
||||
}
|
||||
this.callback(visitTime * 1000, transitionType, lastKnownTitle);
|
||||
|
||||
PlacesObservers.removeListener(["page-visited"], this.handlePlacesEvent);
|
||||
}
|
||||
}
|
||||
this.callback(time, transitionType, lastKnownTitle);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Tests that a title was set properly in the database.
|
||||
|
@ -983,15 +984,15 @@ add_task(async function test_title_change_notifies() {
|
|||
});
|
||||
|
||||
let visitPromise = new Promise(resolve => {
|
||||
function onVisits(events) {
|
||||
Assert.equal(events.length, 1, "Should only get notified for one visit.");
|
||||
Assert.equal(events[0].type, "page-visited");
|
||||
let {url} = events[0];
|
||||
Assert.equal(url, place.uri.spec, "Should get notified for visiting the new URI.");
|
||||
PlacesObservers.removeListener(["page-visited"], onVisits);
|
||||
resolve();
|
||||
}
|
||||
PlacesObservers.addListener(["page-visited"], onVisits);
|
||||
PlacesUtils.history.addObserver({
|
||||
onVisits(visits) {
|
||||
Assert.equal(visits.length, 1, "Should only get notified for one visit.");
|
||||
let {uri} = visits[0];
|
||||
Assert.equal(uri.spec, place.uri.spec, "Should get notified for visiting the new URI.");
|
||||
PlacesUtils.history.removeObserver(this);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
asyncHistory.updatePlaces(place);
|
||||
await visitPromise;
|
||||
|
@ -1027,15 +1028,17 @@ add_task(async function test_visit_notifies() {
|
|||
resolve();
|
||||
}
|
||||
};
|
||||
new VisitObserver(place.uri, place.guid,
|
||||
let visitObserver = new VisitObserver(place.uri, place.guid,
|
||||
function(aVisitDate,
|
||||
aTransitionType) {
|
||||
let visit = place.visits[0];
|
||||
Assert.equal(visit.visitDate, aVisitDate);
|
||||
Assert.equal(visit.transitionType, aTransitionType);
|
||||
|
||||
PlacesUtils.history.removeObserver(visitObserver);
|
||||
finisher();
|
||||
});
|
||||
PlacesUtils.history.addObserver(visitObserver);
|
||||
let observer = function(aSubject, aTopic, aData) {
|
||||
info("observe(" + aSubject + ", " + aTopic + ", " + aData + ")");
|
||||
Assert.ok(aSubject instanceof Ci.nsIURI);
|
||||
|
@ -1266,14 +1269,16 @@ add_task(async function test_title_on_initial_visit() {
|
|||
guid: "mnopqrstuvwx",
|
||||
};
|
||||
let visitPromise = new Promise(resolve => {
|
||||
new VisitObserver(place.uri, place.guid,
|
||||
function(aVisitDate,
|
||||
aTransitionType,
|
||||
aLastKnownTitle) {
|
||||
let visitObserver = new VisitObserver(place.uri, place.guid,
|
||||
function(aVisitDate,
|
||||
aTransitionType,
|
||||
aLastKnownTitle) {
|
||||
Assert.equal(place.title, aLastKnownTitle);
|
||||
|
||||
PlacesUtils.history.removeObserver(visitObserver);
|
||||
resolve();
|
||||
});
|
||||
PlacesUtils.history.addObserver(visitObserver);
|
||||
});
|
||||
await promiseUpdatePlaces(place);
|
||||
await visitPromise;
|
||||
|
@ -1288,14 +1293,16 @@ add_task(async function test_title_on_initial_visit() {
|
|||
guid: "fghijklmnopq",
|
||||
};
|
||||
visitPromise = new Promise(resolve => {
|
||||
new VisitObserver(place.uri, place.guid,
|
||||
function(aVisitDate,
|
||||
aTransitionType,
|
||||
aLastKnownTitle) {
|
||||
let visitObserver = new VisitObserver(place.uri, place.guid,
|
||||
function(aVisitDate,
|
||||
aTransitionType,
|
||||
aLastKnownTitle) {
|
||||
Assert.equal(place.title, aLastKnownTitle);
|
||||
|
||||
PlacesUtils.history.removeObserver(visitObserver);
|
||||
resolve();
|
||||
});
|
||||
PlacesUtils.history.addObserver(visitObserver);
|
||||
});
|
||||
await promiseUpdatePlaces(place);
|
||||
await visitPromise;
|
||||
|
@ -1309,14 +1316,16 @@ add_task(async function test_title_on_initial_visit() {
|
|||
guid: "fghijklmnopq",
|
||||
};
|
||||
visitPromise = new Promise(resolve => {
|
||||
new VisitObserver(place.uri, place.guid,
|
||||
function(aVisitDate,
|
||||
aTransitionType,
|
||||
aLastKnownTitle) {
|
||||
let visitObserver = new VisitObserver(place.uri, place.guid,
|
||||
function(aVisitDate,
|
||||
aTransitionType,
|
||||
aLastKnownTitle) {
|
||||
Assert.equal(null, aLastKnownTitle);
|
||||
|
||||
PlacesUtils.history.removeObserver(visitObserver);
|
||||
resolve();
|
||||
});
|
||||
PlacesUtils.history.addObserver(visitObserver);
|
||||
});
|
||||
await promiseUpdatePlaces(place);
|
||||
await visitPromise;
|
||||
|
|
|
@ -44,6 +44,9 @@ add_task(async function test_remove_single() {
|
|||
observer = {
|
||||
onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch() {},
|
||||
onVisits(aVisits) {
|
||||
reject(new Error("Unexpected call to onVisits " + aVisits.length));
|
||||
},
|
||||
onTitleChanged(aUri) {
|
||||
reject(new Error("Unexpected call to onTitleChanged " + aUri.spec));
|
||||
},
|
||||
|
|
|
@ -292,6 +292,9 @@ function getObserverPromise(bookmarkedUri) {
|
|||
observer = {
|
||||
onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch() {},
|
||||
onVisits() {
|
||||
reject(new Error("Unexpected call to onVisits"));
|
||||
},
|
||||
onTitleChanged(aUri) {
|
||||
reject(new Error("Unexpected call to onTitleChanged"));
|
||||
},
|
||||
|
|
|
@ -134,6 +134,9 @@ add_task(async function test_removeVisitsByFilter() {
|
|||
deferred: PromiseUtils.defer(),
|
||||
onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch() {},
|
||||
onVisits(aVisits) {
|
||||
this.deferred.reject(new Error("Unexpected call to onVisits " + aVisits.length));
|
||||
},
|
||||
onTitleChanged(uri) {
|
||||
this.deferred.reject(new Error("Unexpected call to onTitleChanged " + uri.spec));
|
||||
},
|
||||
|
|
|
@ -11,11 +11,11 @@ var visit_count = 0;
|
|||
async function task_add_visit(aURI, aVisitType) {
|
||||
// Wait for a visits notification and get the visitId.
|
||||
let visitId;
|
||||
let visitsPromise = PlacesTestUtils.waitForNotification("page-visited", visits => {
|
||||
let visitsPromise = PlacesTestUtils.waitForNotification("onVisits", visits => {
|
||||
visitId = visits[0].visitId;
|
||||
let {url} = visits[0];
|
||||
return url == aURI.spec;
|
||||
}, "places");
|
||||
let {uri} = visits[0];
|
||||
return uri.equals(aURI);
|
||||
}, "history");
|
||||
|
||||
// Add visits.
|
||||
await PlacesTestUtils.addVisits([{
|
||||
|
|
|
@ -20,28 +20,29 @@ const PRIVATE_URI = NetUtil.newURI("http://www.example.net/");
|
|||
* Callback function to be called with the same arguments of onVisit.
|
||||
*/
|
||||
function waitForOnVisit(aCallback) {
|
||||
function listener(aEvents) {
|
||||
Assert.equal(aEvents.length, 1, "Right number of visits notified");
|
||||
Assert.equal(aEvents[0].type, "page-visited");
|
||||
let {
|
||||
url,
|
||||
visitId,
|
||||
visitTime,
|
||||
referringVisitId,
|
||||
transitionType,
|
||||
pageGuid,
|
||||
hidden,
|
||||
visitCount,
|
||||
typedCount,
|
||||
lastKnownTitle,
|
||||
} = aEvents[0];
|
||||
PlacesObservers.removeListener(["page-visited"], listener);
|
||||
let uriArg = NetUtil.newURI(url);
|
||||
aCallback(uriArg, visitId, visitTime, 0, referringVisitId,
|
||||
transitionType, pageGuid, hidden, visitCount,
|
||||
typedCount, lastKnownTitle);
|
||||
}
|
||||
PlacesObservers.addListener(["page-visited"], listener);
|
||||
let historyObserver = {
|
||||
__proto__: NavHistoryObserver.prototype,
|
||||
onVisits: function HO_onVisit(aVisits) {
|
||||
Assert.equal(aVisits.length, 1, "Right number of visits notified");
|
||||
let {
|
||||
uri,
|
||||
visitId,
|
||||
time,
|
||||
referrerId,
|
||||
transitionType,
|
||||
guid,
|
||||
hidden,
|
||||
visitCount,
|
||||
typed,
|
||||
lastKnownTitle,
|
||||
} = aVisits[0];
|
||||
PlacesUtils.history.removeObserver(this);
|
||||
aCallback(uri, visitId, time, 0, referrerId,
|
||||
transitionType, guid, hidden, visitCount,
|
||||
typed, lastKnownTitle);
|
||||
}
|
||||
};
|
||||
PlacesUtils.history.addObserver(historyObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -156,11 +157,11 @@ add_task(async function test_dh_addBookmarkRemoveDownload() {
|
|||
add_task(async function test_dh_addDownload_referrer() {
|
||||
// Wait for visits notification and get the visit id.
|
||||
let visitId;
|
||||
let referrerPromise = PlacesTestUtils.waitForNotification("page-visited", visits => {
|
||||
let referrerPromise = PlacesTestUtils.waitForNotification("onVisits", visits => {
|
||||
visitId = visits[0].visitId;
|
||||
let {url} = visits[0];
|
||||
return url == REFERRER_URI.spec;
|
||||
}, "places");
|
||||
let {uri} = visits[0];
|
||||
return uri.equals(REFERRER_URI);
|
||||
}, "history");
|
||||
|
||||
await PlacesTestUtils.addVisits([{
|
||||
uri: REFERRER_URI,
|
||||
|
@ -174,17 +175,16 @@ add_task(async function test_dh_addDownload_referrer() {
|
|||
|
||||
// Wait for visits notification and get the referrer Id.
|
||||
let referrerId;
|
||||
let downloadPromise = PlacesTestUtils.waitForNotification("page-visited", visits => {
|
||||
referrerId = visits[0].referringVisitId;
|
||||
let {url} = visits[0];
|
||||
return url == DOWNLOAD_URI.spec;
|
||||
}, "places");
|
||||
let downloadPromise = PlacesTestUtils.waitForNotification("onVisits", visits => {
|
||||
referrerId = visits[0].referrerId;
|
||||
let {uri} = visits[0];
|
||||
return uri.equals(DOWNLOAD_URI);
|
||||
}, "history");
|
||||
|
||||
gDownloadHistory.addDownload(DOWNLOAD_URI, REFERRER_URI, Date.now() * 1000);
|
||||
await downloadPromise;
|
||||
|
||||
// Verify results for download uri.
|
||||
// ensure that we receive the 'page-visited' notification before we call addDownload.
|
||||
Assert.ok(!!PlacesTestUtils.isPageInDB(DOWNLOAD_URI));
|
||||
Assert.equal(visitId, referrerId);
|
||||
|
||||
|
@ -260,6 +260,7 @@ add_test(function test_dh_details() {
|
|||
let historyObserver = {
|
||||
onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch() {},
|
||||
onVisits() {},
|
||||
onTitleChanged: function HO_onTitleChanged(aURI, aPageTitle) {
|
||||
if (aURI.equals(SOURCE_URI)) {
|
||||
titleSet = true;
|
||||
|
|
|
@ -10,6 +10,7 @@ function NavHistoryObserver() {
|
|||
NavHistoryObserver.prototype = {
|
||||
onBeginUpdateBatch() { },
|
||||
onEndUpdateBatch() { },
|
||||
onVisits() { },
|
||||
onTitleChanged() { },
|
||||
onDeleteURI() { },
|
||||
onClearHistory() { },
|
||||
|
@ -35,23 +36,6 @@ function onNotify(callback) {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a one-time places observer for 'page-visited',
|
||||
* which resolves a promise on being called.
|
||||
*/
|
||||
function promiseVisitAdded(callback) {
|
||||
return new Promise(resolve => {
|
||||
function listener(events) {
|
||||
PlacesObservers.removeListener(["page-visited"], listener);
|
||||
Assert.equal(events.length, 1, "Right number of visits notified");
|
||||
Assert.equal(events[0].type, "page-visited");
|
||||
callback(events[0]);
|
||||
resolve();
|
||||
}
|
||||
PlacesObservers.addListener(["page-visited"], listener);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronous task that adds a visit to the history database.
|
||||
*/
|
||||
|
@ -66,18 +50,19 @@ async function task_add_visit(uri, timestamp, transition) {
|
|||
return [uri, timestamp];
|
||||
}
|
||||
|
||||
add_task(async function test_visitAdded() {
|
||||
let promiseNotify = promiseVisitAdded(function(visit) {
|
||||
add_task(async function test_onVisits() {
|
||||
let promiseNotify = onNotify(function onVisits(aVisits) {
|
||||
Assert.equal(aVisits.length, 1, "Right number of visits notified");
|
||||
let visit = aVisits[0];
|
||||
Assert.ok(visit.uri.equals(testuri));
|
||||
Assert.ok(visit.visitId > 0);
|
||||
Assert.equal(visit.url, testuri.spec);
|
||||
Assert.equal(visit.visitTime, testtime / 1000);
|
||||
Assert.equal(visit.referringVisitId, 0);
|
||||
Assert.equal(visit.time, testtime);
|
||||
Assert.equal(visit.referrerId, 0);
|
||||
Assert.equal(visit.transitionType, TRANSITION_TYPED);
|
||||
let uri = NetUtil.newURI(visit.url);
|
||||
do_check_guid_for_uri(uri, visit.pageGuid);
|
||||
do_check_guid_for_uri(visit.uri, visit.guid);
|
||||
Assert.ok(!visit.hidden);
|
||||
Assert.equal(visit.visitCount, 1);
|
||||
Assert.equal(visit.typedCount, 1);
|
||||
Assert.equal(visit.typed, 1);
|
||||
});
|
||||
let testuri = NetUtil.newURI("http://firefox.com/");
|
||||
let testtime = Date.now() * 1000;
|
||||
|
@ -85,18 +70,19 @@ add_task(async function test_visitAdded() {
|
|||
await promiseNotify;
|
||||
});
|
||||
|
||||
add_task(async function test_visitAdded() {
|
||||
let promiseNotify = promiseVisitAdded(function(visit) {
|
||||
add_task(async function test_onVisits() {
|
||||
let promiseNotify = onNotify(function onVisits(aVisits) {
|
||||
Assert.equal(aVisits.length, 1, "Right number of visits notified");
|
||||
let visit = aVisits[0];
|
||||
Assert.ok(visit.uri.equals(testuri));
|
||||
Assert.ok(visit.visitId > 0);
|
||||
Assert.equal(visit.url, testuri.spec);
|
||||
Assert.equal(visit.visitTime, testtime / 1000);
|
||||
Assert.equal(visit.referringVisitId, 0);
|
||||
Assert.equal(visit.time, testtime);
|
||||
Assert.equal(visit.referrerId, 0);
|
||||
Assert.equal(visit.transitionType, TRANSITION_FRAMED_LINK);
|
||||
let uri = NetUtil.newURI(visit.url);
|
||||
do_check_guid_for_uri(uri, visit.pageGuid);
|
||||
do_check_guid_for_uri(visit.uri, visit.guid);
|
||||
Assert.ok(visit.hidden);
|
||||
Assert.equal(visit.visitCount, 1);
|
||||
Assert.equal(visit.typedCount, 0);
|
||||
Assert.equal(visit.typed, 0);
|
||||
});
|
||||
let testuri = NetUtil.newURI("http://hidden.firefox.com/");
|
||||
let testtime = Date.now() * 1000;
|
||||
|
@ -107,43 +93,44 @@ add_task(async function test_visitAdded() {
|
|||
add_task(async function test_multiple_onVisit() {
|
||||
let testuri = NetUtil.newURI("http://self.firefox.com/");
|
||||
let promiseNotifications = new Promise(resolve => {
|
||||
function listener(aEvents) {
|
||||
Assert.equal(aEvents.length, 3, "Right number of visits notified");
|
||||
for (let i = 0; i < aEvents.length; i++) {
|
||||
Assert.equal(aEvents[i].type, "page-visited");
|
||||
let visit = aEvents[i];
|
||||
Assert.equal(testuri.spec, visit.url);
|
||||
Assert.ok(visit.visitId > 0);
|
||||
Assert.ok(visit.visitTime > 0);
|
||||
Assert.ok(!visit.hidden);
|
||||
let uri = NetUtil.newURI(visit.url);
|
||||
do_check_guid_for_uri(uri, visit.pageGuid);
|
||||
switch (i) {
|
||||
case 0:
|
||||
Assert.equal(visit.referringVisitId, 0);
|
||||
Assert.equal(visit.transitionType, TRANSITION_LINK);
|
||||
Assert.equal(visit.visitCount, 1);
|
||||
Assert.equal(visit.typedCount, 0);
|
||||
break;
|
||||
case 1:
|
||||
Assert.ok(visit.referringVisitId > 0);
|
||||
Assert.equal(visit.transitionType, TRANSITION_LINK);
|
||||
Assert.equal(visit.visitCount, 2);
|
||||
Assert.equal(visit.typedCount, 0);
|
||||
break;
|
||||
case 2:
|
||||
Assert.equal(visit.referringVisitId, 0);
|
||||
Assert.equal(visit.transitionType, TRANSITION_TYPED);
|
||||
Assert.equal(visit.visitCount, 3);
|
||||
Assert.equal(visit.typedCount, 1);
|
||||
let observer = {
|
||||
__proto__: NavHistoryObserver.prototype,
|
||||
onVisits(aVisits) {
|
||||
Assert.equal(aVisits.length, 3, "Right number of visits notified");
|
||||
for (let i = 0; i < aVisits.length; i++) {
|
||||
let visit = aVisits[i];
|
||||
Assert.ok(testuri.equals(visit.uri));
|
||||
Assert.ok(visit.visitId > 0);
|
||||
Assert.ok(visit.time > 0);
|
||||
Assert.ok(!visit.hidden);
|
||||
do_check_guid_for_uri(visit.uri, visit.guid);
|
||||
switch (i) {
|
||||
case 0:
|
||||
Assert.equal(visit.referrerId, 0);
|
||||
Assert.equal(visit.transitionType, TRANSITION_LINK);
|
||||
Assert.equal(visit.visitCount, 1);
|
||||
Assert.equal(visit.typed, 0);
|
||||
break;
|
||||
case 1:
|
||||
Assert.ok(visit.referrerId > 0);
|
||||
Assert.equal(visit.transitionType, TRANSITION_LINK);
|
||||
Assert.equal(visit.visitCount, 2);
|
||||
Assert.equal(visit.typed, 0);
|
||||
break;
|
||||
case 2:
|
||||
Assert.equal(visit.referrerId, 0);
|
||||
Assert.equal(visit.transitionType, TRANSITION_TYPED);
|
||||
Assert.equal(visit.visitCount, 3);
|
||||
Assert.equal(visit.typed, 1);
|
||||
|
||||
PlacesObservers.removeListener(["page-visited"], listener);
|
||||
resolve();
|
||||
break;
|
||||
PlacesUtils.history.removeObserver(observer, false);
|
||||
resolve();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PlacesObservers.addListener(["page-visited"], listener);
|
||||
},
|
||||
};
|
||||
PlacesUtils.history.addObserver(observer);
|
||||
});
|
||||
await PlacesTestUtils.addVisits([
|
||||
{ uri: testuri, transition: TRANSITION_LINK },
|
||||
|
|
|
@ -12,24 +12,43 @@ var gVisits = [{url: "http://www.mozilla.com/",
|
|||
transition: TRANSITION_LINK}];
|
||||
|
||||
add_task(async function test_execute() {
|
||||
let observer;
|
||||
let completionPromise = new Promise(resolveCompletionPromise => {
|
||||
let visitCount = 0;
|
||||
function listener(aEvents) {
|
||||
Assert.equal(aEvents.length, 1, "Right number of visits notified");
|
||||
Assert.equal(aEvents[0].type, "page-visited");
|
||||
let event = aEvents[0];
|
||||
Assert.equal(event.url, gVisits[visitCount].url);
|
||||
Assert.equal(event.transitionType, gVisits[visitCount].transition);
|
||||
visitCount++;
|
||||
observer = {
|
||||
__proto__: NavHistoryObserver.prototype,
|
||||
_visitCount: 0,
|
||||
onVisit(aURI, aVisitID, aTime, aSessionID, aReferringID,
|
||||
aTransitionType, aAdded) {
|
||||
Assert.equal(aURI.spec, gVisits[this._visitCount].url);
|
||||
Assert.equal(aTransitionType, gVisits[this._visitCount].transition);
|
||||
this._visitCount++;
|
||||
|
||||
if (visitCount == gVisits.length) {
|
||||
resolveCompletionPromise();
|
||||
PlacesObservers.removeListener(["page-visited"], listener);
|
||||
}
|
||||
}
|
||||
PlacesObservers.addListener(["page-visited"], listener);
|
||||
if (this._visitCount == gVisits.length) {
|
||||
resolveCompletionPromise();
|
||||
}
|
||||
},
|
||||
onVisits(aVisits) {
|
||||
Assert.equal(aVisits.length, 1, "Right number of visits notified");
|
||||
let {
|
||||
uri,
|
||||
visitId,
|
||||
time,
|
||||
referrerId,
|
||||
transitionType,
|
||||
guid,
|
||||
hidden,
|
||||
visitCount,
|
||||
typed,
|
||||
lastKnownTitle,
|
||||
} = aVisits[0];
|
||||
this.onVisit(uri, visitId, time, 0, referrerId,
|
||||
transitionType, guid, hidden, visitCount,
|
||||
typed, lastKnownTitle);
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
PlacesUtils.history.addObserver(observer);
|
||||
|
||||
for (var visit of gVisits) {
|
||||
if (visit.transition == TRANSITION_TYPED)
|
||||
|
@ -48,4 +67,5 @@ add_task(async function test_execute() {
|
|||
|
||||
await completionPromise;
|
||||
|
||||
PlacesUtils.history.removeObserver(observer);
|
||||
});
|
||||
|
|
|
@ -827,6 +827,7 @@ var PageThumbsHistoryObserver = {
|
|||
onTitleChanged() {},
|
||||
onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch() {},
|
||||
onVisits() {},
|
||||
onPageChanged() {},
|
||||
onDeleteVisits() {},
|
||||
|
||||
|
|
|
@ -549,9 +549,6 @@ var PlacesProvider = {
|
|||
*/
|
||||
init: function PlacesProvider_init() {
|
||||
PlacesUtils.history.addObserver(this, true);
|
||||
this._placesObserver =
|
||||
new PlacesWeakCallbackWrapper(this.handlePlacesEvents.bind(this));
|
||||
PlacesObservers.addListener(["page-visited"], this._placesObserver);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -659,11 +656,11 @@ var PlacesProvider = {
|
|||
}
|
||||
},
|
||||
|
||||
handlePlacesEvents(aEvents) {
|
||||
onVisits(aVisits) {
|
||||
if (!this._batchProcessingDepth) {
|
||||
for (let event of aEvents) {
|
||||
if (event.visitCount == 1 && event.lastKnownTitle) {
|
||||
this.onTitleChanged(event.url, event.lastKnownTitle, event.pageGuid);
|
||||
for (let visit of aVisits) {
|
||||
if (visit.visitCount == 1 && visit.lastKnownTitle) {
|
||||
this.onTitleChanged(visit.uri, visit.lastKnownTitle, visit.guid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -714,11 +711,8 @@ var PlacesProvider = {
|
|||
* Called by the history service.
|
||||
*/
|
||||
onTitleChanged: function PlacesProvider_onTitleChanged(aURI, aNewTitle, aGUID) {
|
||||
if (aURI instanceof Ci.nsIURI) {
|
||||
aURI = aURI.spec;
|
||||
}
|
||||
this._callObservers("onLinkChanged", {
|
||||
url: aURI,
|
||||
url: aURI.spec,
|
||||
title: aNewTitle
|
||||
});
|
||||
},
|
||||
|
|
|
@ -41,9 +41,6 @@ module.exports = {
|
|||
"MatchPatternSet": false,
|
||||
"MenuBoxObject": false,
|
||||
// Specific to Firefox (Chrome code only).
|
||||
"PlacesObservers": false,
|
||||
"PlacesWeakCallbackWrapper": false,
|
||||
// Specific to Firefox (Chrome code only).
|
||||
"SharedArrayBuffer": false,
|
||||
"SimpleGestureEvent": false,
|
||||
// Note: StopIteration will likely be removed as part of removing legacy
|
||||
|
|
Загрузка…
Ссылка в новой задаче