mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 05:15:45 +00:00
Merge mozilla-central to mozilla-inbound. CLOSED TREE
This commit is contained in:
commit
48178c7559
@ -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,12 +9,6 @@
|
||||
|
||||
#include "nsISelectionListener.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsRange;
|
||||
class nsINode;
|
||||
|
||||
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.
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIContentInlines.h"
|
||||
#include "nsIImageLoadingContent.h"
|
||||
#include "nsITextControlElement.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
@ -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"
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include <nsIMutableArray.h>
|
||||
#include <nsArrayUtils.h>
|
||||
#include <nsPerformanceMetrics.h>
|
||||
#include "nsComponentManagerUtils.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',
|
||||
]
|
||||
|
@ -59,7 +59,7 @@ public:
|
||||
|
||||
void
|
||||
GetPropertyChangeClosure(DeclarationBlockMutationClosure* aClosure,
|
||||
mozilla::MutationClosureData* aClosureData) final
|
||||
MutationClosureData* aClosureData) final
|
||||
{
|
||||
aClosure->function = MutationClosureFunction;
|
||||
aClosure->data = aClosureData;
|
||||
@ -71,7 +71,7 @@ protected:
|
||||
~nsDOMCSSAttributeDeclaration();
|
||||
|
||||
virtual nsresult SetCSSDeclaration(mozilla::DeclarationBlock* aDecl,
|
||||
mozilla::MutationClosureData* aClosureData) override;
|
||||
MutationClosureData* aClosureData) override;
|
||||
virtual nsIDocument* DocToUpdate() override;
|
||||
|
||||
RefPtr<Element> mElement;
|
||||
|
@ -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
|
@ -338,7 +338,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"
|
||||
|
||||
@ -3998,9 +3996,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;
|
||||
}
|
||||
}
|
||||
@ -4013,9 +4008,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
|
||||
@ -4599,27 +4591,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
|
||||
|
Loading…
Reference in New Issue
Block a user