Backed out 5 changesets (bug 1340498) for build bustages on SelectionChangeListener.h on a CLOSED TREE

Backed out changeset c89b86622d38 (bug 1340498)
Backed out changeset b270d4a01986 (bug 1340498)
Backed out changeset 8ed32495b46f (bug 1340498)
Backed out changeset df9a67c58183 (bug 1340498)
Backed out changeset a5977e0708ea (bug 1340498)
This commit is contained in:
arthur.iakab 2018-06-26 07:59:01 +03:00
Родитель 44024fd464
Коммит fc7e217166
73 изменённых файлов: 685 добавлений и 1318 удалений

Просмотреть файл

@ -94,17 +94,17 @@ const getHistoryObserver = () => {
onDeleteURI(uri, guid, reason) {
this.emit("visitRemoved", {allHistory: false, urls: [uri.spec]});
}
handlePlacesEvents(events) {
for (let event of events) {
let visit = {
id: event.pageGuid,
url: event.url,
title: event.lastKnownTitle || "",
lastVisitTime: event.visitTime,
visitCount: event.visitCount,
typedCount: event.typedCount,
onVisits(visits) {
for (let visit of visits) {
let data = {
id: visit.guid,
url: visit.uri.spec,
title: visit.lastKnownTitle || "",
lastVisitTime: visit.time / 1000, // time from Places is microseconds,
visitCount: visit.visitCount,
typedCount: visit.typed,
};
this.emit("visited", visit);
this.emit("visited", data);
}
}
onBeginUpdateBatch() {}
@ -122,9 +122,6 @@ const getHistoryObserver = () => {
this.emit("visitRemoved", {allHistory: false, urls: [uri.spec]});
}
}();
PlacesUtils.observers.addListener(
["page-visited"],
_observer.handlePlacesEvents.bind(_observer));
PlacesUtils.history.addObserver(_observer);
}
return _observer;

Просмотреть файл

@ -631,6 +631,9 @@ add_task(async function checkUndoVisitsState() {
let observer = {
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onVisits(visits) {
wrongMethodDeferred.reject(new Error("Unexpected call to onVisits " + visits.length));
},
onTitleChanged(uri) {
wrongMethodDeferred.reject(new Error("Unexpected call to onTitleChanged " + uri.spec));
},

Просмотреть файл

@ -60,6 +60,7 @@ class HistoryObserver extends Observer {
onEndUpdateBatch() {}
onVisits() {}
onTitleChanged() {}

Просмотреть файл

@ -816,6 +816,7 @@ var AeroPeek = {
/* nsINavHistoryObserver implementation */
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onVisits() {},
onTitleChanged() {},
onFrecencyChanged() {},
onManyFrecenciesChanged() {},

Просмотреть файл

@ -55,6 +55,7 @@ function test() {
var historyObserver = {
onBeginUpdateBatch: function() {},
onEndUpdateBatch: function() {},
onVisits: function() {},
onTitleChanged: function(aURI, aPageTitle) {},
onDeleteURI: function(aURI) {},
onClearHistory: function() {},

Просмотреть файл

@ -15,6 +15,7 @@ add_task(async function() {
var historyObserver = {
onBeginUpdateBatch: function() {},
onEndUpdateBatch: function() {},
onVisits: function() {},
onTitleChanged: function(aURI, aPageTitle) {
aURI = aURI.spec;
switch (aURI) {

Просмотреть файл

@ -48,6 +48,7 @@ function test() {
onBeginUpdateBatch: function() { },
onEndUpdateBatch: function() { },
onVisits: function() { },
onTitleChanged: function() { },
onDeleteURI: function() { },
onClearHistory: function() { },

Просмотреть файл

@ -1,52 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/PlacesEvent.h"
#include "mozilla/HoldDropJSObjects.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_CLASS(PlacesEvent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PlacesEvent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PlacesEvent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(PlacesEvent)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(PlacesEvent, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(PlacesEvent, Release)
already_AddRefed<PlacesEvent>
PlacesEvent::Constructor(const GlobalObject& aGlobal,
PlacesEventType aType,
ErrorResult& rv)
{
RefPtr<PlacesEvent> event = new PlacesEvent(aType);
return event.forget();
}
nsISupports*
PlacesEvent::GetParentObject() const
{
return nullptr;
}
JSObject*
PlacesEvent::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return PlacesEventBinding::Wrap(aCx, this, aGivenProto);
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -1,48 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_PlacesEvent_h
#define mozilla_dom_PlacesEvent_h
#include "mozilla/dom/PlacesEventBinding.h"
#include "mozilla/ErrorResult.h"
#include "nsWrapperCache.h"
namespace mozilla {
namespace dom {
class PlacesEvent : public nsWrapperCache
{
public:
explicit PlacesEvent(PlacesEventType aType)
: mType(aType)
{}
static already_AddRefed<PlacesEvent>
Constructor(const GlobalObject& aGlobal,
PlacesEventType aType,
ErrorResult& aRv);
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(PlacesEvent)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(PlacesEvent)
nsISupports* GetParentObject() const;
JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
PlacesEventType Type() const { return mType; }
virtual const PlacesVisit* AsPlacesVisit() const { return nullptr; }
protected:
virtual ~PlacesEvent() = default;
PlacesEventType mType;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_PlacesEvent_h

Просмотреть файл

@ -1,350 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "PlacesObservers.h"
#include "PlacesWeakCallbackWrapper.h"
#include "nsIWeakReferenceUtils.h"
#include "mozilla/ClearOnShutdown.h"
namespace mozilla {
namespace dom {
template <class T>
struct Flagged
{
Flagged(uint32_t aFlags, T&& aValue)
: flags(aFlags)
, value(std::forward<T>(aValue))
{}
Flagged(Flagged&& aOther)
: Flagged(std::move(aOther.flags), std::move(aOther.value))
{}
Flagged(const Flagged& aOther) = default;
~Flagged() = default;
uint32_t flags;
T value;
};
template <class T>
using FlaggedArray = nsTArray<Flagged<T>>;
template <class T>
struct ListenerCollection
{
static StaticAutoPtr<FlaggedArray<T>> gListeners;
static StaticAutoPtr<FlaggedArray<T>> gListenersToRemove;
static FlaggedArray<T>* GetListeners() {
MOZ_ASSERT(NS_IsMainThread());
if (!gListeners) {
gListeners = new FlaggedArray<T>();
ClearOnShutdown(&gListeners);
}
return gListeners;
}
static FlaggedArray<T>* GetListenersToRemove() {
MOZ_ASSERT(NS_IsMainThread());
if (!gListenersToRemove) {
gListenersToRemove = new FlaggedArray<T>();
ClearOnShutdown(&gListenersToRemove);
}
return gListenersToRemove;
}
};
template <class T>
StaticAutoPtr<FlaggedArray<T>> ListenerCollection<T>::gListeners;
template <class T>
StaticAutoPtr<FlaggedArray<T>> ListenerCollection<T>::gListenersToRemove;
typedef ListenerCollection<RefPtr<PlacesEventCallback>> JSListeners;
typedef ListenerCollection<WeakPtr<PlacesWeakCallbackWrapper>> WeakJSListeners;
typedef ListenerCollection<WeakPtr<places::INativePlacesEventCallback>> WeakNativeListeners;
static bool gCallingListeners = false;
uint32_t
GetEventTypeFlag(PlacesEventType aEventType)
{
if (aEventType == PlacesEventType::None) {
return 0;
}
return 1 << ((uint32_t)aEventType - 1);
}
uint32_t
GetFlagsForEventTypes(const nsTArray<PlacesEventType>& aEventTypes)
{
uint32_t flags = 0;
for (PlacesEventType eventType : aEventTypes) {
flags |= GetEventTypeFlag(eventType);
}
return flags;
}
uint32_t
GetFlagsForEvents(const nsTArray<OwningNonNull<PlacesEvent>>& aEvents)
{
uint32_t flags = 0;
for (const PlacesEvent& event : aEvents) {
flags |= GetEventTypeFlag(event.Type());
}
return flags;
}
template <class TWrapped, class TUnwrapped>
void CallListeners(uint32_t aEventFlags,
FlaggedArray<TWrapped>& aListeners,
const Sequence<OwningNonNull<PlacesEvent>>& aEvents,
const std::function<TUnwrapped(TWrapped&)>& aUnwrapListener,
const std::function<void(TUnwrapped&, const Sequence<OwningNonNull<PlacesEvent>>&)>& aCallListener)
{
for (uint32_t i = 0; i < aListeners.Length(); i++) {
Flagged<TWrapped>& l = aListeners[i];
TUnwrapped unwrapped = aUnwrapListener(l.value);
if (!unwrapped) {
aListeners.RemoveElementAt(i);
i--;
continue;
}
if ((l.flags & aEventFlags) == aEventFlags) {
aCallListener(unwrapped, aEvents);
} else if (l.flags & aEventFlags) {
Sequence<OwningNonNull<PlacesEvent>> filtered;
for (const OwningNonNull<PlacesEvent>& event : aEvents) {
if (l.flags & GetEventTypeFlag(event->Type())) {
bool success = !!filtered.AppendElement(event, fallible);
MOZ_RELEASE_ASSERT(success);
}
}
aCallListener(unwrapped, filtered);
}
}
}
void
PlacesObservers::AddListener(GlobalObject& aGlobal,
const nsTArray<PlacesEventType>& aEventTypes,
PlacesEventCallback& aCallback,
ErrorResult& rv)
{
uint32_t flags = GetFlagsForEventTypes(aEventTypes);
FlaggedArray<RefPtr<PlacesEventCallback>>* listeners =
JSListeners::GetListeners();
Flagged<RefPtr<PlacesEventCallback>> pair(flags, &aCallback);
listeners->AppendElement(pair);
}
void
PlacesObservers::AddListener(GlobalObject& aGlobal,
const nsTArray<PlacesEventType>& aEventTypes,
PlacesWeakCallbackWrapper& aCallback,
ErrorResult& rv)
{
uint32_t flags = GetFlagsForEventTypes(aEventTypes);
FlaggedArray<WeakPtr<PlacesWeakCallbackWrapper>>* listeners =
WeakJSListeners::GetListeners();
WeakPtr<PlacesWeakCallbackWrapper> weakCb(&aCallback);
MOZ_ASSERT(weakCb.get());
Flagged<WeakPtr<PlacesWeakCallbackWrapper>> flagged(flags, std::move(weakCb));
listeners->AppendElement(flagged);
}
void
PlacesObservers::AddListener(const nsTArray<PlacesEventType>& aEventTypes,
places::INativePlacesEventCallback* aCallback)
{
uint32_t flags = GetFlagsForEventTypes(aEventTypes);
FlaggedArray<WeakPtr<places::INativePlacesEventCallback>>* listeners =
WeakNativeListeners::GetListeners();
Flagged<WeakPtr<places::INativePlacesEventCallback>> pair(flags, aCallback);
listeners->AppendElement(pair);
}
void
PlacesObservers::RemoveListener(GlobalObject& aGlobal,
const nsTArray<PlacesEventType>& aEventTypes,
PlacesEventCallback& aCallback,
ErrorResult& rv)
{
uint32_t flags = GetFlagsForEventTypes(aEventTypes);
if (gCallingListeners) {
FlaggedArray<RefPtr<PlacesEventCallback>>* listeners =
JSListeners::GetListenersToRemove();
Flagged<RefPtr<PlacesEventCallback>> pair(flags, &aCallback);
listeners->AppendElement(pair);
} else {
RemoveListener(flags, aCallback);
}
}
void
PlacesObservers::RemoveListener(GlobalObject& aGlobal,
const nsTArray<PlacesEventType>& aEventTypes,
PlacesWeakCallbackWrapper& aCallback,
ErrorResult& rv)
{
uint32_t flags = GetFlagsForEventTypes(aEventTypes);
if (gCallingListeners) {
FlaggedArray<WeakPtr<PlacesWeakCallbackWrapper>>* listeners =
WeakJSListeners::GetListenersToRemove();
WeakPtr<PlacesWeakCallbackWrapper> weakCb(&aCallback);
MOZ_ASSERT(weakCb.get());
Flagged<WeakPtr<PlacesWeakCallbackWrapper>> flagged(flags, std::move(weakCb));
listeners->AppendElement(flagged);
} else {
RemoveListener(flags, aCallback);
}
}
void
PlacesObservers::RemoveListener(const nsTArray<PlacesEventType>& aEventTypes,
places::INativePlacesEventCallback* aCallback)
{
uint32_t flags = GetFlagsForEventTypes(aEventTypes);
if (gCallingListeners) {
FlaggedArray<WeakPtr<places::INativePlacesEventCallback>>* listeners =
WeakNativeListeners::GetListenersToRemove();
Flagged<WeakPtr<places::INativePlacesEventCallback>> pair(flags, aCallback);
listeners->AppendElement(pair);
} else {
RemoveListener(flags, aCallback);
}
}
void
PlacesObservers::RemoveListener(uint32_t aFlags,
PlacesEventCallback& aCallback)
{
FlaggedArray<RefPtr<PlacesEventCallback>>& listeners =
*JSListeners::GetListeners();
for (uint32_t i = 0; i < listeners.Length(); i++) {
Flagged<RefPtr<PlacesEventCallback>>& l = listeners[i];
if (!(*l.value == aCallback)) {
continue;
}
if (l.flags == aFlags) {
listeners.RemoveElementAt(i);
i--;
} else {
l.flags &= ~aFlags;
}
}
}
void
PlacesObservers::RemoveListener(uint32_t aFlags,
PlacesWeakCallbackWrapper& aCallback)
{
FlaggedArray<WeakPtr<PlacesWeakCallbackWrapper>>& listeners =
*WeakJSListeners::GetListeners();
for (uint32_t i = 0; i < listeners.Length(); i++) {
Flagged<WeakPtr<PlacesWeakCallbackWrapper>>& l = listeners[i];
RefPtr<PlacesWeakCallbackWrapper> unwrapped = l.value.get();
if (unwrapped != &aCallback) {
continue;
}
if (l.flags == aFlags) {
listeners.RemoveElementAt(i);
i--;
} else {
l.flags &= ~aFlags;
}
}
}
void
PlacesObservers::RemoveListener(uint32_t aFlags,
places::INativePlacesEventCallback* aCallback)
{
FlaggedArray<WeakPtr<places::INativePlacesEventCallback>>& listeners =
*WeakNativeListeners::GetListeners();
for (uint32_t i = 0; i < listeners.Length(); i++) {
Flagged<WeakPtr<places::INativePlacesEventCallback>>& l = listeners[i];
RefPtr<places::INativePlacesEventCallback> unwrapped = l.value.get();
if (unwrapped != aCallback) {
continue;
}
if (l.flags == aFlags) {
listeners.RemoveElementAt(i);
i--;
} else {
l.flags &= ~aFlags;
}
}
}
void
PlacesObservers::NotifyListeners(GlobalObject& aGlobal,
const Sequence<OwningNonNull<PlacesEvent>>& aEvents,
ErrorResult& rv)
{
NotifyListeners(aEvents);
}
void
PlacesObservers::NotifyListeners(const Sequence<OwningNonNull<PlacesEvent>>& aEvents)
{
MOZ_RELEASE_ASSERT(!gCallingListeners);
gCallingListeners = true;
uint32_t flags = GetFlagsForEvents(aEvents);
CallListeners<RefPtr<PlacesEventCallback>, RefPtr<PlacesEventCallback>>(
flags, *JSListeners::GetListeners(), aEvents,
[](auto& cb) { return cb; },
[&](auto& cb, const auto& events) {
cb->Call(aEvents);
});
CallListeners<WeakPtr<places::INativePlacesEventCallback>,
RefPtr<places::INativePlacesEventCallback>>(
flags, *WeakNativeListeners::GetListeners(), aEvents,
[](auto& cb) { return cb.get(); },
[&](auto& cb, const Sequence<OwningNonNull<PlacesEvent>>& events) {
cb->HandlePlacesEvent(events);
});
CallListeners<WeakPtr<PlacesWeakCallbackWrapper>,
RefPtr<PlacesWeakCallbackWrapper>>(
flags, *WeakJSListeners::GetListeners(), aEvents,
[](auto& cb) { return cb.get(); },
[&](auto& cb, const auto& events) {
cb->mCallback->Call(aEvents);
});
auto& listenersToRemove = *JSListeners::GetListenersToRemove();
if (listenersToRemove.Length() > 0) {
for (auto& listener : listenersToRemove) {
RemoveListener(listener.flags, *listener.value);
}
}
auto& weakListenersToRemove = *WeakJSListeners::GetListenersToRemove();
if (weakListenersToRemove.Length() > 0) {
for (auto& listener : weakListenersToRemove) {
RemoveListener(listener.flags, *listener.value.get());
}
}
auto& nativeListenersToRemove = *WeakNativeListeners::GetListenersToRemove();
if (nativeListenersToRemove.Length() > 0) {
for (auto& listener : nativeListenersToRemove) {
RemoveListener(listener.flags, listener.value.get());
}
}
gCallingListeners = false;
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -1,62 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_PlacesObservers__
#define mozilla_dom_PlacesObservers__
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/PlacesObserversBinding.h"
#include "mozilla/dom/PlacesEvent.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/Pair.h"
#include "mozilla/places/INativePlacesEventCallback.h"
#include "nsIWeakReferenceUtils.h"
namespace mozilla {
namespace dom {
class PlacesObservers
{
public:
static void AddListener(GlobalObject& aGlobal,
const nsTArray<PlacesEventType>& aEventTypes,
PlacesEventCallback& aCallback,
ErrorResult& rv);
static void AddListener(GlobalObject& aGlobal,
const nsTArray<PlacesEventType>& aEventTypes,
PlacesWeakCallbackWrapper& aCallback,
ErrorResult& rv);
static void AddListener(const nsTArray<PlacesEventType>& aEventTypes,
places::INativePlacesEventCallback* aCallback);
static void RemoveListener(GlobalObject& aGlobal,
const nsTArray<PlacesEventType>& aEventTypes,
PlacesEventCallback& aCallback,
ErrorResult& rv);
static void RemoveListener(GlobalObject& aGlobal,
const nsTArray<PlacesEventType>& aEventTypes,
PlacesWeakCallbackWrapper& aCallback,
ErrorResult& rv);
static void RemoveListener(const nsTArray<PlacesEventType>& aEventTypes,
places::INativePlacesEventCallback* aCallback);
static void NotifyListeners(GlobalObject& aGlobal,
const Sequence<OwningNonNull<PlacesEvent>>& aEvents,
ErrorResult& rv);
static void NotifyListeners(const Sequence<OwningNonNull<PlacesEvent>>& aEvents);
private:
static void RemoveListener(uint32_t aFlags, PlacesEventCallback& aCallback);
static void RemoveListener(uint32_t aFlags, PlacesWeakCallbackWrapper& aCallback);
static void RemoveListener(uint32_t aFlags, places::INativePlacesEventCallback* aCallback);
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_PlacesObservers__

Просмотреть файл

@ -1,67 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_PlacesVisit_h
#define mozilla_dom_PlacesVisit_h
#include "mozilla/dom/PlacesEvent.h"
namespace mozilla {
namespace dom {
class PlacesVisit final : public PlacesEvent
{
public:
explicit PlacesVisit() : PlacesEvent(PlacesEventType::Page_visited) {}
static already_AddRefed<PlacesVisit>
Constructor(const GlobalObject& aGlobal,
ErrorResult& aRv) {
RefPtr<PlacesVisit> event = new PlacesVisit();
return event.forget();
}
JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override
{
return PlacesVisitBinding::Wrap(aCx, this, aGivenProto);
}
const PlacesVisit* AsPlacesVisit() const override { return this; }
void GetUrl(nsString& aUrl) { aUrl = mUrl; }
uint64_t VisitId() { return mVisitId; }
uint64_t VisitTime() { return mVisitTime; }
uint64_t ReferringVisitId() { return mReferringVisitId; }
uint64_t TransitionType() { return mTransitionType; }
void GetPageGuid(nsTString<char>& aPageGuid) { aPageGuid = mPageGuid; }
bool Hidden() { return mHidden; }
uint32_t VisitCount() { return mVisitCount; }
uint32_t TypedCount() { return mTypedCount; }
void GetLastKnownTitle(nsString& aLastKnownTitle) { aLastKnownTitle = mLastKnownTitle; }
// It's convenient for these to be directly available in C++, so just expose
// them. These are generally passed around with const qualifiers anyway, so
// it shouldn't be a problem.
nsString mUrl;
uint64_t mVisitId;
uint64_t mVisitTime;
uint64_t mReferringVisitId;
uint32_t mTransitionType;
nsCString mPageGuid;
bool mHidden;
uint32_t mVisitCount;
uint32_t mTypedCount;
nsString mLastKnownTitle;
private:
~PlacesVisit() = default;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_PlacesVisit_h

Просмотреть файл

@ -1,55 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/PlacesWeakCallbackWrapper.h"
#include "mozilla/HoldDropJSObjects.h"
#include "mozilla/dom/ProcessGlobal.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PlacesWeakCallbackWrapper, mParent, mCallback)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(PlacesWeakCallbackWrapper, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(PlacesWeakCallbackWrapper, Release)
PlacesWeakCallbackWrapper::PlacesWeakCallbackWrapper(nsISupports* aParent,
PlacesEventCallback& aCallback)
: mParent(do_GetWeakReference(aParent))
, mCallback(&aCallback)
{
}
already_AddRefed<PlacesWeakCallbackWrapper>
PlacesWeakCallbackWrapper::Constructor(const GlobalObject& aGlobal,
PlacesEventCallback& aCallback,
ErrorResult& rv)
{
nsCOMPtr<nsISupports> parent = aGlobal.GetAsSupports();
RefPtr<PlacesWeakCallbackWrapper> wrapper =
new PlacesWeakCallbackWrapper(parent, aCallback);
return wrapper.forget();
}
PlacesWeakCallbackWrapper::~PlacesWeakCallbackWrapper()
{
}
nsISupports*
PlacesWeakCallbackWrapper::GetParentObject() const
{
nsCOMPtr<nsISupports> parent = do_QueryReferent(mParent);
return parent;
}
JSObject*
PlacesWeakCallbackWrapper::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return PlacesWeakCallbackWrapperBinding::Wrap(aCx, this, aGivenProto);
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -1,49 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_PlacesWeakCallbackWrapper_h
#define mozilla_dom_PlacesWeakCallbackWrapper_h
#include "mozilla/dom/PlacesObserversBinding.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/Pair.h"
#include "nsWrapperCache.h"
namespace mozilla {
namespace dom {
class PlacesWeakCallbackWrapper final : public nsWrapperCache
, public SupportsWeakPtr<PlacesWeakCallbackWrapper>
{
public:
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(PlacesWeakCallbackWrapper)
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(PlacesWeakCallbackWrapper)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(PlacesWeakCallbackWrapper)
explicit PlacesWeakCallbackWrapper(nsISupports* aParent,
PlacesEventCallback& aCallback);
static already_AddRefed<PlacesWeakCallbackWrapper>
Constructor(const GlobalObject& aGlobal,
PlacesEventCallback& aCallback,
ErrorResult& rv);
nsISupports* GetParentObject() const;
JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
protected:
friend class PlacesObservers;
~PlacesWeakCallbackWrapper();
nsWeakPtr mParent;
RefPtr<PlacesEventCallback> mCallback;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_PlacesWeakCallbackWrapper_h

Просмотреть файл

@ -9,11 +9,6 @@
#include "nsISelectionListener.h"
#include "mozilla/Attributes.h"
#include "nsCycleCollectionParticipant.h"
#include "nsTArray.h"
#include "nsCOMPtr.h"
class nsRange;
namespace mozilla {
namespace dom {

Просмотреть файл

@ -6,6 +6,7 @@
#include "mozilla/Preferences.h"
#include "mozilla/dom/ShadowRoot.h"
#include "mozilla/dom/ShadowRootBinding.h"
#include "mozilla/dom/DocumentFragment.h"
#include "ChildIterator.h"
#include "nsContentUtils.h"

Просмотреть файл

@ -10,12 +10,9 @@
#include "mozilla/dom/DocumentFragment.h"
#include "mozilla/dom/DocumentOrShadowRoot.h"
#include "mozilla/dom/NameSpaceConstants.h"
#include "mozilla/dom/ShadowRootBinding.h"
#include "mozilla/ServoBindings.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIdentifierMapEntry.h"
#include "nsStubMutationObserver.h"
#include "nsTHashtable.h"
class nsAtom;

Просмотреть файл

@ -7,7 +7,6 @@
#ifndef mozilla_dom_StyleSheetList_h
#define mozilla_dom_StyleSheetList_h
#include "nsContentUtils.h"
#include "mozilla/dom/DocumentOrShadowRoot.h"
#include "nsStubMutationObserver.h"
#include "nsWrapperCache.h"

Просмотреть файл

@ -8,7 +8,6 @@
#include "nsIAppStartup.h"
#include "nsToolkitCompsCID.h"
#include "nsCOMPtr.h"
#include "nsContentUtils.h"
namespace mozilla {

Просмотреть файл

@ -201,10 +201,6 @@ EXPORTS.mozilla.dom += [
'NodeInfoInlines.h',
'NodeIterator.h',
'ParentProcessMessageManager.h',
'PlacesEvent.h',
'PlacesObservers.h',
'PlacesVisit.h',
'PlacesWeakCallbackWrapper.h',
'Pose.h',
'ProcessGlobal.h',
'ProcessMessageManager.h',
@ -394,13 +390,6 @@ if CONFIG['FUZZING']:
'FuzzingFunctions.cpp',
]
if CONFIG['MOZ_PLACES']:
UNIFIED_SOURCES += [
'PlacesEvent.cpp',
'PlacesObservers.cpp',
'PlacesWeakCallbackWrapper.cpp',
]
# these files couldn't be in UNIFIED_SOURCES for now for reasons given below:
SOURCES += [
# Several conflicts with other bindings.

Просмотреть файл

@ -24,8 +24,6 @@
using namespace mozilla;
using namespace mozilla::dom;
using mozilla::dom::DocGroup;
using mozilla::dom::HTMLSlotElement;
AutoTArray<RefPtr<nsDOMMutationObserver>, 4>*
nsDOMMutationObserver::sScheduledMutationObservers = nullptr;

Просмотреть файл

@ -15,7 +15,6 @@
using mozilla::MallocSizeOf;
using mozilla::Maybe;
using mozilla::DOMEventTargetHelper;
using mozilla::dom::BlobURLProtocolHandler;
using mozilla::dom::ClientInfo;
using mozilla::dom::ServiceWorker;
using mozilla::dom::ServiceWorkerDescriptor;

Просмотреть файл

@ -90,7 +90,6 @@
#include "nsUnicharUtils.h"
#include "nsXBLBinding.h"
#include "nsXBLPrototypeBinding.h"
#include "nsWindowSizes.h"
#include "mozilla/Preferences.h"
#include "xpcpublic.h"
#include "HTMLLegendElement.h"

Просмотреть файл

@ -25,7 +25,6 @@
#endif
using namespace mozilla;
using namespace mozilla::dom;
StaticRefPtr<nsWindowMemoryReporter> sWindowReporter;

Просмотреть файл

@ -12,7 +12,6 @@
#include "nsXHTMLContentSerializer.h"
#include "mozilla/dom/Element.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsElementTable.h"
@ -31,6 +30,7 @@
#include "nsStubMutationObserver.h"
#include "nsAttrName.h"
#include "nsComputedDOMStyle.h"
#include "mozilla/dom/Element.h"
using namespace mozilla;

Просмотреть файл

@ -1,69 +0,0 @@
enum PlacesEventType {
"none",
/**
* data: PlacesVisit. Fired whenever a page is visited.
*/
"page-visited",
};
[ChromeOnly, Exposed=(Window,System)]
interface PlacesEvent {
readonly attribute PlacesEventType type;
};
[ChromeOnly, Exposed=(Window,System)]
interface PlacesVisit : PlacesEvent {
/**
* URL of the visit.
*/
readonly attribute DOMString url;
/**
* Id of the visit.
*/
readonly attribute unsigned long long visitId;
/**
* Time of the visit, in milliseconds since epoch.
*/
readonly attribute unsigned long long visitTime;
/**
* The id of the visit the user came from, defaults to 0 for no referrer.
*/
readonly attribute unsigned long long referringVisitId;
/**
* One of nsINavHistory.TRANSITION_*
*/
readonly attribute unsigned long transitionType;
/**
* The unique id associated with the page.
*/
readonly attribute ByteString pageGuid;
/**
* Whether the visited page is marked as hidden.
*/
readonly attribute boolean hidden;
/**
* Number of visits (including this one) for this URL.
*/
readonly attribute unsigned long visitCount;
/**
* Whether the URL has been typed or not.
* TODO (Bug 1271801): This will become a count, rather than a boolean.
* For future compatibility, always compare it with "> 0".
*/
readonly attribute unsigned long typedCount;
/**
* The last known title of the page. Might not be from the current visit,
* and might be null if it is not known.
*/
readonly attribute DOMString? lastKnownTitle;
};

Просмотреть файл

@ -1,32 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
callback PlacesEventCallback = void (sequence<PlacesEvent> events);
[ChromeOnly, Exposed=(Window,System),
Constructor(PlacesEventCallback callback)]
interface PlacesWeakCallbackWrapper {
};
// Global singleton which should handle all events for places.
[ChromeOnly, Exposed=(Window,System)]
namespace PlacesObservers {
[Throws]
void addListener(sequence<PlacesEventType> eventTypes,
PlacesEventCallback listener);
[Throws]
void addListener(sequence<PlacesEventType> eventTypes,
PlacesWeakCallbackWrapper listener);
[Throws]
void removeListener(sequence<PlacesEventType> eventTypes,
PlacesEventCallback listener);
[Throws]
void removeListener(sequence<PlacesEventType> eventTypes,
PlacesWeakCallbackWrapper listener);
[Throws]
void notifyListeners(sequence<PlacesEvent> events);
};

Просмотреть файл

@ -46,9 +46,3 @@ WEBIDL_FILES = [
'WebExtensionContentScript.webidl',
'WebExtensionPolicy.webidl',
]
if CONFIG['MOZ_PLACES']:
WEBIDL_FILES += [
'PlacesEvent.webidl',
'PlacesObservers.webidl',
]

Просмотреть файл

@ -483,17 +483,11 @@ HistoryTracker.prototype = {
onStart() {
this._log.info("Adding Places observer.");
PlacesUtils.history.addObserver(this, true);
this._placesObserver =
new PlacesWeakCallbackWrapper(this.handlePlacesEvents.bind(this));
PlacesObservers.addListener(["page-visited"], this._placesObserver);
},
onStop() {
this._log.info("Removing Places observer.");
PlacesUtils.history.removeObserver(this);
if (this._placesObserver) {
PlacesObservers.removeListener(["page-visited"], this._placesObserver);
}
},
QueryInterface: ChromeUtils.generateQI([
@ -524,20 +518,19 @@ HistoryTracker.prototype = {
);
},
handlePlacesEvents(aEvents) {
this.asyncObserver.enqueueCall(() => this._handlePlacesEvents(aEvents));
onVisits(aVisits) {
this.asyncObserver.enqueueCall(() => this._onVisits(aVisits));
},
async _handlePlacesEvents(aEvents) {
async _onVisits(aVisits) {
if (this.ignoreAll) {
this._log.trace("ignoreAll: ignoring visits [" +
aEvents.map(v => v.guid).join(",") + "]");
aVisits.map(v => v.guid).join(",") + "]");
return;
}
for (let event of aEvents) {
this._log.trace("'page-visited': " + event.url);
if (this.engine.shouldSyncURL(event.url) &&
await this.addChangedID(event.pageGuid)) {
for (let {uri, guid} of aVisits) {
this._log.trace("onVisits: " + uri.spec);
if (this.engine.shouldSyncURL(uri.spec) && (await this.addChangedID(guid))) {
this.score += SCORE_INCREMENT_SMALL;
}
}

Просмотреть файл

@ -549,18 +549,15 @@ async function serverForFoo(engine, callback) {
async function promiseVisit(expectedType, expectedURI) {
return new Promise(resolve => {
function done(type, uri) {
if (uri == expectedURI.spec && type == expectedType) {
if (uri.equals(expectedURI) && type == expectedType) {
PlacesUtils.history.removeObserver(observer);
PlacesObservers.removeListener(["page-visited"],
observer.handlePlacesEvents);
resolve();
}
}
let observer = {
handlePlacesEvents(events) {
Assert.equal(events.length, 1);
Assert.equal(events[0].type, "page-visited");
done("added", events[0].url);
onVisits(visits) {
Assert.equal(visits.length, 1);
done("added", visits[0].uri);
},
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
@ -568,15 +565,13 @@ async function promiseVisit(expectedType, expectedURI) {
onFrecencyChanged() {},
onManyFrecenciesChanged() {},
onDeleteURI(uri) {
done("removed", uri.spec);
done("removed", uri);
},
onClearHistory() {},
onPageChanged() {},
onDeleteVisits() {},
};
PlacesUtils.history.addObserver(observer, false);
PlacesObservers.addListener(["page-visited"],
observer.handlePlacesEvents);
});
}

Просмотреть файл

@ -13,11 +13,26 @@ const TIMESTAMP3 = (Date.now() - 123894) * 1000;
function promiseOnVisitObserved() {
return new Promise(res => {
let listener = new PlacesWeakCallbackWrapper((events) => {
PlacesObservers.removeListener(["page-visited"], listener);
res();
});
PlacesObservers.addListener(["page-visited"], listener);
PlacesUtils.history.addObserver({
onBeginUpdateBatch: function onBeginUpdateBatch() {},
onEndUpdateBatch: function onEndUpdateBatch() {},
onPageChanged: function onPageChanged() {},
onTitleChanged: function onTitleChanged() {
},
onVisits: function onVisits() {
PlacesUtils.history.removeObserver(this);
res();
},
onDeleteVisits: function onDeleteVisits() {},
onPageExpired: function onPageExpired() {},
onDeleteURI: function onDeleteURI() {},
onClearHistory: function onClearHistory() {},
QueryInterface: ChromeUtils.generateQI([
Ci.nsINavHistoryObserver,
Ci.nsINavHistoryObserver_MOZILLA_1_9_1_ADDITIONS,
Ci.nsISupportsWeakReference
])
}, true);
});
}

Просмотреть файл

@ -1022,6 +1022,7 @@ this.DownloadHistoryObserver.prototype = {
onTitleChanged() {},
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onVisits() {},
onPageChanged() {},
onDeleteVisits() {},
};

Просмотреть файл

@ -2400,7 +2400,7 @@ add_task(async function test_history() {
// The history notifications should be received before the download completes.
let [time, transitionType] = await promiseVisit;
Assert.equal(time, download.startTime.getTime());
Assert.equal(time, download.startTime.getTime() * 1000);
Assert.equal(transitionType, Ci.nsINavHistoryService.TRANSITION_DOWNLOAD);
// Restart and complete the download after clearing history.
@ -2434,7 +2434,7 @@ add_task(async function test_history_tryToKeepPartialData() {
// The time set by nsIHelperAppService may be different than the start time in
// the download object, thus we only check that it is a meaningful time. Note
// that we subtract one second from the earliest time to account for rounding.
Assert.ok(time >= beforeStartTimeMs - 1000);
Assert.ok(time >= beforeStartTimeMs * 1000 - 1000000);
// Complete the download before finishing the test.
continueResponses();

Просмотреть файл

@ -146,16 +146,32 @@ function promiseTimeout(aTime) {
*/
function promiseWaitForVisit(aUrl) {
return new Promise(resolve => {
function listener(aEvents) {
Assert.equal(aEvents.length, 1);
let event = aEvents[0];
Assert.equal(event.type, "page-visited");
if (event.url == aUrl) {
PlacesObservers.removeListener(["page-visited"], listener);
resolve([event.visitTime, event.transitionType]);
}
}
PlacesObservers.addListener(["page-visited"], listener);
let uri = NetUtil.newURI(aUrl);
PlacesUtils.history.addObserver({
QueryInterface: ChromeUtils.generateQI([Ci.nsINavHistoryObserver]),
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onVisits(aVisits) {
Assert.equal(aVisits.length, 1);
let {
uri: visitUri,
time,
transitionType,
} = aVisits[0];
if (visitUri.equals(uri)) {
PlacesUtils.history.removeObserver(this);
resolve([time, transitionType]);
}
},
onTitleChanged() {},
onDeleteURI() {},
onClearHistory() {},
onPageChanged() {},
onDeleteVisits() {},
});
});
}

Просмотреть файл

@ -38,10 +38,6 @@
#include "nsTHashtable.h"
#include "jsapi.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/PlacesObservers.h"
#include "mozilla/dom/PlacesVisit.h"
#include "mozilla/dom/ProcessGlobal.h"
#include "mozilla/dom/ScriptSettings.h"
// Initial size for the cache holding visited status observers.
#define VISIT_OBSERVERS_INITIAL_CACHE_LENGTH 64
@ -173,6 +169,121 @@ struct VisitData {
bool useFrecencyRedirectBonus;
};
////////////////////////////////////////////////////////////////////////////////
//// nsVisitData
class nsVisitData : public nsIVisitData
{
public:
explicit nsVisitData(nsIURI* aURI,
int64_t aVisitId,
PRTime aTime,
int64_t aReferrerVisitId,
int32_t aTransitionType,
const nsACString& aGuid,
bool aHidden,
uint32_t aVisitCount,
uint32_t aTyped,
const nsAString& aLastKnownTitle)
: mURI(aURI)
, mVisitId(aVisitId)
, mTime(aTime)
, mReferrerVisitId(aReferrerVisitId)
, mTransitionType(aTransitionType)
, mGuid(aGuid)
, mHidden(aHidden)
, mVisitCount(aVisitCount)
, mTyped(aTyped)
, mLastKnownTitle(aLastKnownTitle)
{
MOZ_ASSERT(NS_IsMainThread(),
"nsVisitData should only be constructed on the main thread.");
}
NS_DECL_ISUPPORTS
NS_IMETHOD GetUri(nsIURI** aUri) override
{
NS_ENSURE_ARG_POINTER(aUri);
*aUri = mURI;
NS_IF_ADDREF(*aUri);
return NS_OK;
}
NS_IMETHOD GetVisitId(int64_t* aVisitId) override
{
*aVisitId = mVisitId;
return NS_OK;
}
NS_IMETHOD GetTime(PRTime* aTime) override
{
*aTime = mTime;
return NS_OK;
}
NS_IMETHOD GetReferrerId(int64_t* aReferrerVisitId) override
{
*aReferrerVisitId = mReferrerVisitId;
return NS_OK;
}
NS_IMETHOD GetTransitionType(uint32_t* aTransitionType) override
{
*aTransitionType = mTransitionType;
return NS_OK;
}
NS_IMETHOD GetGuid(nsACString& aGuid) override
{
aGuid.Assign(mGuid);
return NS_OK;
}
NS_IMETHOD GetHidden(bool* aHidden) override
{
*aHidden = mHidden;
return NS_OK;
}
NS_IMETHOD GetVisitCount(uint32_t* aVisitCount) override
{
*aVisitCount = mVisitCount;
return NS_OK;
}
NS_IMETHOD GetTyped(uint32_t* aTyped) override
{
*aTyped = mTyped;
return NS_OK;
}
NS_IMETHOD GetLastKnownTitle(nsAString& aLastKnownTitle) override
{
aLastKnownTitle.Assign(mLastKnownTitle);
return NS_OK;
}
private:
virtual ~nsVisitData() {
MOZ_ASSERT(NS_IsMainThread(),
"nsVisitData should only be destructed on the main thread.");
};
nsCOMPtr<nsIURI> mURI;
int64_t mVisitId;
PRTime mTime;
int64_t mReferrerVisitId;
uint32_t mTransitionType;
nsCString mGuid;
bool mHidden;
uint32_t mVisitCount;
uint32_t mTyped;
nsString mLastKnownTitle;
};
NS_IMPL_ISUPPORTS(nsVisitData, nsIVisitData)
////////////////////////////////////////////////////////////////////////////////
//// RemoveVisitsFilter
@ -670,28 +781,21 @@ public:
aNavHistory->NotifyTitleChange(aURI, aPlace.title, aPlace.guid);
}
aNavHistory->UpdateDaysOfHistory(aPlace.visitTime);
return NS_OK;
}
void AddPlaceForNotify(const VisitData& aPlace,
nsIURI* aURI,
Sequence<OwningNonNull<PlacesEvent>>& aEvents) {
nsCOMArray<nsIVisitData>& aPlaces) {
if (aPlace.transitionType != nsINavHistoryService::TRANSITION_EMBED) {
RefPtr<PlacesVisit> vd = new PlacesVisit();
vd->mVisitId = aPlace.visitId;
vd->mUrl.Assign(NS_ConvertUTF8toUTF16(aPlace.spec));
vd->mVisitTime = aPlace.visitTime / 1000;
vd->mReferringVisitId = aPlace.referrerVisitId;
vd->mTransitionType = aPlace.transitionType;
vd->mPageGuid.Assign(aPlace.guid);
vd->mHidden = aPlace.hidden;
vd->mVisitCount = aPlace.visitCount + 1; // Add current visit
vd->mTypedCount = static_cast<uint32_t>(aPlace.typed);
vd->mLastKnownTitle.Assign(aPlace.title);
bool success = !!aEvents.AppendElement(vd.forget(), fallible);
MOZ_RELEASE_ASSERT(success);
nsCOMPtr<nsIVisitData> notifyPlace = new nsVisitData(
aURI, aPlace.visitId, aPlace.visitTime,
aPlace.referrerVisitId, aPlace.transitionType,
aPlace.guid, aPlace.hidden,
aPlace.visitCount + 1, // Add current visit.
static_cast<uint32_t>(aPlace.typed),
aPlace.title);
aPlaces.AppendElement(notifyPlace.forget());
}
}
@ -714,7 +818,7 @@ public:
nsCOMPtr<nsIObserverService> obsService =
mozilla::services::GetObserverService();
Sequence<OwningNonNull<PlacesEvent>> events;
nsCOMArray<nsIVisitData> places;
nsCOMArray<nsIURI> uris;
if (mPlaces.Length() > 0) {
for (uint32_t i = 0; i < mPlaces.Length(); ++i) {
@ -723,7 +827,7 @@ public:
if (!uri) {
return NS_ERROR_UNEXPECTED;
}
AddPlaceForNotify(mPlaces[i], uri, events);
AddPlaceForNotify(mPlaces[i], uri, places);
uris.AppendElement(uri.forget());
}
} else {
@ -732,12 +836,11 @@ public:
if (!uri) {
return NS_ERROR_UNEXPECTED;
}
AddPlaceForNotify(mPlace, uri, events);
AddPlaceForNotify(mPlace, uri, places);
uris.AppendElement(uri.forget());
}
if (events.Length() > 0) {
PlacesObservers::NotifyListeners(events);
if (places.Length() > 0) {
navHistory->NotifyOnVisits(places.Elements(), places.Length());
}
PRTime now = PR_Now();

Просмотреть файл

@ -1,34 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_image_INativePlacesEventCallback_h
#define mozilla_image_INativePlacesEventCallback_h
#include "mozilla/dom/PlacesObserversBinding.h"
#include "mozilla/WeakPtr.h"
#include "nsISupports.h"
#include "nsTArray.h"
namespace mozilla {
namespace places {
class INativePlacesEventCallback : public SupportsWeakPtr<INativePlacesEventCallback>
{
public:
typedef dom::Sequence<OwningNonNull<dom::PlacesEvent>> PlacesEventSequence;
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(INativePlacesEventCallback)
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
virtual void HandlePlacesEvent(const PlacesEventSequence& aEvents) = 0;
protected:
virtual ~INativePlacesEventCallback() { }
};
} // namespace places
} // namespace mozilla
#endif // mozilla_image_INativePlacesEventCallback_h

Просмотреть файл

@ -339,7 +339,6 @@ var PlacesUtils = {
TOPIC_BOOKMARKS_RESTORE_FAILED: "bookmarks-restore-failed",
ACTION_SCHEME: "moz-action:",
observers: PlacesObservers,
/**
* GUIDs associated with virtual queries that are used for displaying the

Просмотреть файл

@ -29,7 +29,6 @@ if CONFIG['MOZ_PLACES']:
EXPORTS.mozilla.places = [
'Database.h',
'History.h',
'INativePlacesEventCallback.h',
'Shutdown.h',
]

Просмотреть файл

@ -63,8 +63,6 @@ interface mozIAsyncLivemarks : nsISupports
*/
void reloadLivemarks([optional]in boolean aForceUpdate);
void handlePlacesEvents(in jsval aEvents);
jsval invalidateCachedLivemarks();
};

Просмотреть файл

@ -29,6 +29,67 @@ interface nsINavHistoryQueryOptions;
interface nsINavHistoryResult;
interface nsINavHistoryBatchCallback;
/**
* This interface exists specifically for passing visit information
* in bulk to onVisits below.
*/
[scriptable, uuid(9d8df1ff-142f-4ca7-9f45-3c62a508c7e2)]
interface nsIVisitData : nsISupports
{
/**
* URI of the visit that was just created.
*/
readonly attribute nsIURI uri;
/**
* Id of the visit that was just created.
*/
readonly attribute long long visitId;
/**
* Time of the visit.
*/
readonly attribute PRTime time;
/**
* The id of the visit the user came from, defaults to 0 for no referrer.
*/
readonly attribute long long referrerId;
/**
* One of nsINavHistory.TRANSITION_*
*/
readonly attribute unsigned long transitionType;
/**
* The unique id associated with the page.
*/
readonly attribute ACString guid;
/**
* Whether the visited page is marked as hidden.
*/
readonly attribute boolean hidden;
/**
* Number of visits (included this one) for this URI.
*/
readonly attribute unsigned long visitCount;
/**
* Whether the URI has been typed or not.
* TODO (Bug 1271801): This will become a count, rather than a boolean.
* For future compatibility, always compare it with "> 0".
*/
readonly attribute unsigned long typed;
/**
* The last known title of the page. Might not be from the current visit,
* and might be null if it is not known.
*/
readonly attribute AString lastKnownTitle;
};
[scriptable, uuid(91d104bb-17ef-404b-9f9a-d9ed8de6824c)]
interface nsINavHistoryResultNode : nsISupports
{
@ -581,6 +642,18 @@ interface nsINavHistoryObserver : nsISupports
*/
void onEndUpdateBatch();
/**
* Called everytime a URI is visited, or once for a batch of visits if visits were
* added in bulk.
*
* @note TRANSITION_EMBED visits (corresponding to images in a page, for
* example) are not displayed in history results. Most observers can
* ignore TRANSITION_EMBED visit notifications (which will comprise the
* majority of visit notifications) to save work.
*/
void onVisits([array, size_is(aVisitsCount)] in nsIVisitData aVisits,
in unsigned long aVisitsCount);
/**
* Called whenever either the "real" title or the custom title of the page
* changed. BOTH TITLES ARE ALWAYS INCLUDED in this notification, even though

Просмотреть файл

@ -12,12 +12,8 @@ ChromeUtils.defineModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyGetter(this, "history", function() {
let livemarks = PlacesUtils.livemarks;
// Lazily add an history observer when it's actually needed.
PlacesUtils.history.addObserver(livemarks, true);
let listener = new PlacesWeakCallbackWrapper(
livemarks.handlePlacesEvents.bind(livemarks));
PlacesObservers.addListener(["page-visited"], listener);
PlacesUtils.history.addObserver(PlacesUtils.livemarks, true);
return PlacesUtils.history;
});
@ -340,21 +336,6 @@ LivemarkService.prototype = {
return this._invalidateCachedLivemarks();
},
handlePlacesEvents(aEvents) {
if (!aEvents) {
throw new Components.Exception("Invalid arguments",
Cr.NS_ERROR_INVALID_ARG);
}
this._withLivemarksMap(livemarksMap => {
for (let event of aEvents) {
for (let livemark of livemarksMap.values()) {
livemark.updateURIVisitedStatus(event.url, true);
}
}
});
},
// nsINavBookmarkObserver
onBeginUpdateBatch() {},
@ -431,6 +412,16 @@ LivemarkService.prototype = {
});
},
onVisits(aVisits) {
this._withLivemarksMap(livemarksMap => {
for (let {uri} of aVisits) {
for (let livemark of livemarksMap.values()) {
livemark.updateURIVisitedStatus(uri, true);
}
}
});
},
// nsISupports
classID: Components.ID("{dca61eb5-c7cd-4df1-b0fb-d0722baba251}"),
@ -701,18 +692,18 @@ Livemark.prototype = {
/**
* Updates the visited status of nodes observing this livemark.
*
* @param href
* @param aURI
* If provided will update nodes having the given uri,
* otherwise any node.
* @param visitedStatus
* @param aVisitedStatus
* Whether the nodes should be set as visited.
*/
updateURIVisitedStatus(href, visitedStatus) {
updateURIVisitedStatus(aURI, aVisitedStatus) {
let wasVisited = false;
for (let child of this.children) {
if (!href || child.uri.spec == href) {
if (!aURI || child.uri.equals(aURI)) {
wasVisited = child.visited;
child.visited = visitedStatus;
child.visited = aVisitedStatus;
}
}
@ -720,7 +711,7 @@ Livemark.prototype = {
if (this._nodes.has(container)) {
let nodes = this._nodes.get(container);
for (let node of nodes) {
if (!href || node.uri == href) {
if (!aURI || node.uri == aURI.spec) {
Services.tm.dispatchToMainThread(() => {
observer.nodeHistoryDetailsChanged(node, node.time, wasVisited);
});
@ -827,7 +818,6 @@ LivemarkLoadListener.prototype = {
this._livemark.children = livemarkChildren;
} catch (ex) {
Cu.reportError(ex);
this.abort(ex);
} finally {
this._processor.listener = null;

Просмотреть файл

@ -17,8 +17,6 @@
#include "nsQueryObject.h"
#include "mozilla/Preferences.h"
#include "mozilla/storage.h"
#include "mozilla/dom/PlacesObservers.h"
#include "mozilla/dom/PlacesVisit.h"
#include "GeckoProfiler.h"
@ -214,9 +212,6 @@ nsNavBookmarks::Init()
nsNavHistory* history = nsNavHistory::GetHistoryService();
NS_ENSURE_STATE(history);
history->AddObserver(this, true);
AutoTArray<PlacesEventType, 1> events;
events.AppendElement(PlacesEventType::Page_visited);
PlacesObservers::AddListener(events, this);
// DO NOT PUT STUFF HERE that can fail. See observer comment above.
@ -2058,28 +2053,30 @@ nsNavBookmarks::OnEndUpdateBatch()
}
void
nsNavBookmarks::HandlePlacesEvent(const PlacesEventSequence& aEvents)
NS_IMETHODIMP
nsNavBookmarks::OnVisits(nsIVisitData** aVisits, uint32_t aVisitsCount)
{
for (const auto& event : aEvents) {
if (NS_WARN_IF(event->Type() != PlacesEventType::Page_visited)) {
continue;
}
NS_ENSURE_ARG(aVisits);
NS_ENSURE_ARG(aVisitsCount);
const dom::PlacesVisit* visit = event->AsPlacesVisit();
if (NS_WARN_IF(!visit)) {
continue;
}
for (uint32_t i = 0; i < aVisitsCount; ++i) {
nsIVisitData* place = aVisits[i];
nsCOMPtr<nsIURI> uri;
MOZ_ALWAYS_SUCCEEDS(place->GetUri(getter_AddRefs(uri)));
// If the page is bookmarked, notify observers for each associated bookmark.
ItemVisitData visitData;
visitData.visitId = visit->mVisitId;
visitData.bookmark.url = NS_ConvertUTF16toUTF8(visit->mUrl);
visitData.time = visit->mVisitTime * 1000;
visitData.transitionType = visit->mTransitionType;
nsresult rv = uri->GetSpec(visitData.bookmark.url);
NS_ENSURE_SUCCESS(rv, rv);
MOZ_ALWAYS_SUCCEEDS(place->GetVisitId(&visitData.visitId));
MOZ_ALWAYS_SUCCEEDS(place->GetTime(&visitData.time));
MOZ_ALWAYS_SUCCEEDS(place->GetTransitionType(&visitData.transitionType));
RefPtr< AsyncGetBookmarksForURI<ItemVisitMethod, ItemVisitData> > notifier =
new AsyncGetBookmarksForURI<ItemVisitMethod, ItemVisitData>(this, &nsNavBookmarks::NotifyItemVisited, visitData);
notifier->Init();
}
return NS_OK;
}

Просмотреть файл

@ -78,7 +78,6 @@ class nsNavBookmarks final : public nsINavBookmarksService
, public nsINavHistoryObserver
, public nsIObserver
, public nsSupportsWeakReference
, public mozilla::places::INativePlacesEventCallback
{
public:
NS_DECL_ISUPPORTS
@ -208,16 +207,6 @@ public:
*/
void NotifyItemChanged(const ItemChangeData& aData);
/**
* Part of INativePlacesEventCallback - handles events from the places
* observer system.
* @param aCx
* A JSContext for extracting the values from aEvents.
* @param aEvents
* An array of weakly typed events detailing what changed.
*/
void HandlePlacesEvent(const PlacesEventSequence& aEvents) override;
static const int32_t kGetChildrenIndex_Guid;
static const int32_t kGetChildrenIndex_Position;
static const int32_t kGetChildrenIndex_Type;

Просмотреть файл

@ -521,15 +521,25 @@ nsNavHistory::LoadPrefs()
}
void
nsNavHistory::UpdateDaysOfHistory(PRTime visitTime)
nsNavHistory::NotifyOnVisits(nsIVisitData** aVisits, uint32_t aVisitsCount)
{
MOZ_ASSERT(aVisits, "Can't call NotifyOnVisits with a NULL aVisits");
MOZ_ASSERT(aVisitsCount, "Should have at least 1 visit when notifying");
if (mDaysOfHistory == 0) {
mDaysOfHistory = 1;
}
if (visitTime > mLastCachedEndOfDay || visitTime < mLastCachedStartOfDay) {
mDaysOfHistory = -1;
for (uint32_t i = 0; i < aVisitsCount; ++i) {
PRTime time;
MOZ_ALWAYS_SUCCEEDS(aVisits[i]->GetTime(&time));
if (time > mLastCachedEndOfDay || time < mLastCachedStartOfDay) {
mDaysOfHistory = -1;
}
}
NOTIFY_OBSERVERS(mCanNotify, mObservers, nsINavHistoryObserver,
OnVisits(aVisits, aVisitsCount));
}
void

Просмотреть файл

@ -435,10 +435,9 @@ public:
}
/**
* Updates and invalidates the mDaysOfHistory cache. Should be
* called whenever a visit is added.
* Fires onVisits event to nsINavHistoryService observers
*/
void UpdateDaysOfHistory(PRTime visitTime);
void NotifyOnVisits(nsIVisitData** aVisits, uint32_t aVisitsCount);
/**
* Fires onTitleChanged event to nsINavHistoryService observers

Просмотреть файл

@ -19,8 +19,6 @@
#include "nsUnicharUtils.h"
#include "prtime.h"
#include "nsQueryObject.h"
#include "mozilla/dom/PlacesObservers.h"
#include "mozilla/dom/PlacesVisit.h"
#include "nsCycleCollectionParticipant.h"
@ -3997,9 +3995,6 @@ nsNavHistoryResult::StopObserving()
nsNavHistory* history = nsNavHistory::GetHistoryService();
if (history) {
history->RemoveObserver(this);
AutoTArray<PlacesEventType, 1> events;
events.AppendElement(PlacesEventType::Page_visited);
PlacesObservers::RemoveListener(events, this);
mIsHistoryObserver = false;
}
}
@ -4012,9 +4007,6 @@ nsNavHistoryResult::AddHistoryObserver(nsNavHistoryQueryResultNode* aNode)
nsNavHistory* history = nsNavHistory::GetHistoryService();
NS_ASSERTION(history, "Can't create history service");
history->AddObserver(this, true);
AutoTArray<PlacesEventType, 1> events;
events.AppendElement(PlacesEventType::Page_visited);
PlacesObservers::AddListener(events, this);
mIsHistoryObserver = true;
}
// Don't add duplicate observers. In some case we don't unregister when
@ -4598,27 +4590,32 @@ nsNavHistoryResult::OnVisit(nsIURI* aURI, int64_t aVisitId, PRTime aTime,
}
void
nsNavHistoryResult::HandlePlacesEvent(const PlacesEventSequence& aEvents) {
for (const auto& event : aEvents) {
if (NS_WARN_IF(event->Type() != PlacesEventType::Page_visited)) {
continue;
}
const dom::PlacesVisit* visit = event->AsPlacesVisit();
if (NS_WARN_IF(!visit)) {
continue;
}
NS_IMETHODIMP
nsNavHistoryResult::OnVisits(nsIVisitData** aVisits,
uint32_t aVisitsCount) {
for (uint32_t i = 0; i < aVisitsCount; ++i) {
nsIVisitData* place = aVisits[i];
nsCOMPtr<nsIURI> uri;
MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), visit->mUrl));
if (!uri) {
return;
}
OnVisit(uri, visit->mVisitId, visit->mVisitTime * 1000,
visit->mTransitionType, visit->mPageGuid,
visit->mHidden, visit->mVisitCount, visit->mLastKnownTitle);
MOZ_ALWAYS_SUCCEEDS(place->GetUri(getter_AddRefs(uri)));
int64_t visitId;
MOZ_ALWAYS_SUCCEEDS(place->GetVisitId(&visitId));
PRTime time;
MOZ_ALWAYS_SUCCEEDS(place->GetTime(&time));
uint32_t transitionType;
MOZ_ALWAYS_SUCCEEDS(place->GetTransitionType(&transitionType));
nsCString guid;
MOZ_ALWAYS_SUCCEEDS(place->GetGuid(guid));
bool hidden;
MOZ_ALWAYS_SUCCEEDS(place->GetHidden(&hidden));
uint32_t visitCount;
MOZ_ALWAYS_SUCCEEDS(place->GetVisitCount(&visitCount));
nsString lastKnownTitle;
MOZ_ALWAYS_SUCCEEDS(place->GetLastKnownTitle(lastKnownTitle));
nsresult rv = OnVisit(uri, visitId, time, transitionType, guid, hidden,
visitCount, lastKnownTitle);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}

Просмотреть файл

@ -12,7 +12,6 @@
#ifndef nsNavHistoryResult_h_
#define nsNavHistoryResult_h_
#include "INativePlacesEventCallback.h"
#include "nsTArray.h"
#include "nsInterfaceHashtable.h"
#include "nsDataHashtable.h"
@ -99,8 +98,7 @@ private:
class nsNavHistoryResult final : public nsSupportsWeakReference,
public nsINavHistoryResult,
public nsINavBookmarkObserver,
public nsINavHistoryObserver,
public mozilla::places::INativePlacesEventCallback
public nsINavHistoryObserver
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_NAVHISTORYRESULT_IID)
@ -109,6 +107,8 @@ public:
NS_DECL_NSINAVHISTORYRESULT
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsNavHistoryResult, nsINavHistoryResult)
NS_DECL_BOOKMARK_HISTORY_OBSERVER_EXTERNAL(override)
NS_IMETHOD OnVisits(nsIVisitData** aVisits,
uint32_t aVisitsCount) override;
void AddHistoryObserver(nsNavHistoryQueryResultNode* aNode);
void AddBookmarkFolderObserver(nsNavHistoryFolderResultNode* aNode, int64_t aFolder);
@ -174,8 +174,6 @@ public:
ContainerObserverList mRefreshParticipants;
void requestRefresh(nsNavHistoryContainerResultNode* aContainer);
void HandlePlacesEvent(const PlacesEventSequence& aEvents) override;
void OnMobilePrefChanged();
static void OnMobilePrefChangedCallback(const char* prefName, void* closure);

Просмотреть файл

@ -536,6 +536,7 @@ nsPlacesExpiration.prototype = {
this.status = STATUS.CLEAN;
},
onVisits() {},
onTitleChanged() {},
onDeleteURI() {},
onPageChanged() {},

Просмотреть файл

@ -318,18 +318,6 @@ var PlacesTestUtils = Object.freeze({
},
waitForNotification(notification, conditionFn = () => true, type = "bookmarks") {
if (type == "places") {
return new Promise(resolve => {
function listener(events) {
if (conditionFn(events)) {
PlacesObservers.removeListener([notification], listener);
resolve();
}
}
PlacesObservers.addListener([notification], listener);
});
}
let iface = type == "bookmarks" ? Ci.nsINavBookmarkObserver
: Ci.nsINavHistoryObserver;
return new Promise(resolve => {

Просмотреть файл

@ -15,33 +15,43 @@ add_task(async function() {
];
// Create and add history observer.
let count = 0;
let expectedURI = null;
function onVisitsListener(aEvents) {
for (let event of aEvents) {
info("Received onVisits: " + event.url);
if (event.url == expectedURI) {
count++;
let historyObserver = {
count: 0,
expectedURI: null,
onVisits(aVisits) {
for (let {uri} of aVisits) {
info("Received onVisits: " + uri.spec);
if (uri.equals(this.expectedURI)) {
this.count++;
}
}
}
}
},
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onTitleChanged() {},
onDeleteURI() {},
onClearHistory() {},
onPageChanged() {},
onDeleteVisits() {},
QueryInterface: ChromeUtils.generateQI([Ci.nsINavHistoryObserver])
};
async function promiseLoadedThreeTimes(uri) {
count = 0;
expectedURI = uri;
historyObserver.count = 0;
historyObserver.expectedURI = Services.io.newURI(uri);
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
PlacesObservers.addListener(["page-visited"], onVisitsListener);
PlacesUtils.history.addObserver(historyObserver);
gBrowser.loadURI(uri);
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, uri);
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, uri);
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, uri);
PlacesObservers.removeListener(["page-visited"], onVisitsListener);
PlacesUtils.history.removeObserver(historyObserver);
BrowserTestUtils.removeTab(tab);
}
for (let uri of URIS) {
await promiseLoadedThreeTimes(uri);
is(count, 1,
"'page-visited' has been received right number of times for " + uri);
is(historyObserver.count, 1,
"onVisit has been received right number of times for " + uri);
}
});

Просмотреть файл

@ -23,6 +23,7 @@ add_task(async function() {
onBeginUpdateBatch() { },
onEndUpdateBatch() { },
onVisits() { },
onDeleteURI() { },
onClearHistory() { },
onPageChanged() { },

Просмотреть файл

@ -11,18 +11,19 @@ add_task(async function() {
const FINAL_URI = NetUtil.newURI(BASE_URL + "final.html");
let promiseVisits = new Promise(resolve => {
let observer = {
PlacesUtils.history.addObserver({
__proto__: NavHistoryObserver.prototype,
_notified: [],
onVisit(uri, id, time, referrerId, transition) {
info("Received onVisit: " + uri);
info("Received onVisit: " + uri.spec);
this._notified.push(uri);
if (uri != FINAL_URI.spec) {
if (!uri.equals(FINAL_URI)) {
return;
}
is(this._notified.length, 4);
PlacesObservers.removeListener(["page-visited"], this.handleEvents);
PlacesUtils.history.removeObserver(this);
(async function() {
// Get all pages visited from the original typed one
@ -44,21 +45,18 @@ add_task(async function() {
resolve();
})();
},
handleEvents(events) {
is(events.length, 1, "Right number of visits notified");
is(events[0].type, "page-visited");
onVisits(visits) {
is(visits.length, 1, "Right number of visits notified");
let {
url,
uri,
visitId,
visitTime,
referringVisitId,
time,
referrerId,
transitionType,
} = events[0];
this.onVisit(url, visitId, visitTime, referringVisitId, transitionType);
} = visits[0];
this.onVisit(uri, visitId, time, referrerId, transitionType);
}
};
observer.handleEvents = observer.handleEvents.bind(observer);
PlacesObservers.addListener(["page-visited"], observer.handleEvents);
});
});
PlacesUtils.history.markPageAsTyped(TEST_URI);

Просмотреть файл

@ -32,15 +32,15 @@ async function check_uri(uri, frecency, hidden) {
async function waitVisitedNotifications() {
let redirectNotified = false;
await PlacesTestUtils.waitForNotification("page-visited", visits => {
await PlacesTestUtils.waitForNotification("onVisits", visits => {
is(visits.length, 1, "Was notified for the right number of visits.");
let {url} = visits[0];
info("Received 'page-visited': " + url);
if (url == REDIRECT_URI.spec) {
let {uri} = visits[0];
info("Received onVisits: " + uri.spec);
if (uri.equals(REDIRECT_URI)) {
redirectNotified = true;
}
return url == TARGET_URI.spec;
}, "places");
return uri.equals(TARGET_URI);
}, "history");
return redirectNotified;
}

Просмотреть файл

@ -10,24 +10,42 @@ add_task(async function() {
// Create and add history observer.
let visitedPromise = new Promise(resolve => {
function listener(aEvents) {
is(aEvents.length, 1, "Right number of visits notified");
is(aEvents[0].type, "page-visited");
let uri = NetUtil.newURI(aEvents[0].url);
PlacesObservers.removeListener(["page-visited"], listener);
info("Received 'page-visited': " + uri.spec);
fieldForUrl(uri, "frecency", function(aFrecency) {
is(aFrecency, 0, "Frecency should be 0");
fieldForUrl(uri, "hidden", function(aHidden) {
is(aHidden, 0, "Page should not be hidden");
fieldForUrl(uri, "typed", function(aTyped) {
is(aTyped, 0, "page should not be marked as typed");
resolve();
let historyObserver = {
onVisit(aURI, aVisitID, aTime, aReferringID, aTransitionType) {
PlacesUtils.history.removeObserver(historyObserver);
info("Received onVisit: " + aURI.spec);
fieldForUrl(aURI, "frecency", function(aFrecency) {
is(aFrecency, 0, "Frecency should be 0");
fieldForUrl(aURI, "hidden", function(aHidden) {
is(aHidden, 0, "Page should not be hidden");
fieldForUrl(aURI, "typed", function(aTyped) {
is(aTyped, 0, "page should not be marked as typed");
resolve();
});
});
});
});
}
PlacesObservers.addListener(["page-visited"], listener);
},
onVisits(aVisits) {
is(aVisits.length, 1, "Right number of visits notified");
let {
uri,
visitId,
time,
referrerId,
transitionType,
} = aVisits[0];
this.onVisit(uri, visitId, time, referrerId, transitionType);
},
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onTitleChanged() {},
onDeleteURI() {},
onClearHistory() {},
onPageChanged() {},
onDeleteVisits() {},
QueryInterface: ChromeUtils.generateQI([Ci.nsINavHistoryObserver])
};
PlacesUtils.history.addObserver(historyObserver);
});
let newTabPromise = BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);

Просмотреть файл

@ -3,20 +3,19 @@ const TEST_PATH = getRootDirectory(gTestPath).replace("chrome://mochitests/conte
add_task(async function checkTitleNotificationForNavigation() {
const EXPECTED_URL = Services.io.newURI(TEST_PATH + "empty_page.html");
let promiseTitleChanged = new Promise(resolve => {
function onVisits(aEvents) {
Assert.equal(aEvents.length, 1, "Right number of visits notified");
Assert.equal(aEvents[0].type, "page-visited");
let {
url,
lastKnownTitle,
} = aEvents[0];
info("'page-visited': " + url);
if (url == EXPECTED_URL.spec) {
Assert.equal(lastKnownTitle, null, "Should not have a title");
}
PlacesObservers.removeListener(["page-visited"], onVisits);
}
let obs = {
onVisits(aVisits) {
Assert.equal(aVisits.length, 1, "Right number of visits notified");
let {
uri,
lastKnownTitle,
} = aVisits[0];
info("onVisits: " + uri.spec);
if (uri.equals(EXPECTED_URL)) {
Assert.equal(lastKnownTitle, null, "Should not have a title");
}
},
onTitleChanged(aURI, aTitle, aGuid) {
if (aURI.equals(EXPECTED_URL)) {
is(aTitle, "I am an empty page", "Should have correct title in titlechanged notification");
@ -26,7 +25,6 @@ add_task(async function checkTitleNotificationForNavigation() {
},
};
PlacesUtils.history.addObserver(obs);
PlacesObservers.addListener(["page-visited"], onVisits);
});
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, EXPECTED_URL.spec);
await promiseTitleChanged;

Просмотреть файл

@ -39,15 +39,15 @@ add_task(async function redirect_check_new_typed_visit() {
redirectTargetFrecency += TYPED_VISIT_BONUS;
let redirectNotified = false;
let visitedPromise = PlacesTestUtils.waitForNotification("page-visited", visits => {
let visitedPromise = PlacesTestUtils.waitForNotification("onVisits", visits => {
is(visits.length, 1, "Was notified for the right number of visits.");
let {url} = visits[0];
info("Received 'page-visited': " + url);
if (url == REDIRECT_URI.spec) {
let {uri} = visits[0];
info("Received onVisits for: " + uri.spec);
if (uri.equals(REDIRECT_URI)) {
redirectNotified = true;
}
return url == TARGET_URI.spec;
}, "places");
return uri.equals(TARGET_URI);
}, "history");
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, REDIRECT_URI.spec);
info("Waiting for onVisits");
@ -68,15 +68,15 @@ add_task(async function redirect_check_second_typed_visit() {
redirectTargetFrecency += TYPED_VISIT_BONUS;
let redirectNotified = false;
let visitedPromise = PlacesTestUtils.waitForNotification("page-visited", visits => {
let visitedPromise = PlacesTestUtils.waitForNotification("onVisits", visits => {
is(visits.length, 1, "Was notified for the right number of visits.");
let {url} = visits[0];
info("Received 'page-visited': " + url);
if (url == REDIRECT_URI.spec) {
let {uri} = visits[0];
info("Received onVisits: " + uri.spec);
if (uri.equals(REDIRECT_URI)) {
redirectNotified = true;
}
return url == TARGET_URI.spec;
}, "places");
return uri.equals(TARGET_URI);
}, "history");
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, REDIRECT_URI.spec);
info("Waiting for onVisits");
@ -95,15 +95,15 @@ add_task(async function redirect_check_subsequent_link_visit() {
redirectTargetFrecency += LINK_VISIT_BONUS;
let redirectNotified = false;
let visitedPromise = PlacesTestUtils.waitForNotification("page-visited", visits => {
let visitedPromise = PlacesTestUtils.waitForNotification("onVisits", visits => {
is(visits.length, 1, "Was notified for the right number of visits.");
let {url} = visits[0];
info("Received 'page-visited': " + url);
if (url == REDIRECT_URI.spec) {
let {uri} = visits[0];
info("Received onVisits: " + uri.spec);
if (uri.equals(REDIRECT_URI)) {
redirectNotified = true;
}
return url == TARGET_URI.spec;
}, "places");
return uri.equals(TARGET_URI);
}, "history");
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, REDIRECT_URI.spec);
info("Waiting for onVisits");

Просмотреть файл

@ -25,6 +25,7 @@ add_task(async function() {
data: [],
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onVisits() {},
onTitleChanged(aURI, aPageTitle, aGUID) {
this.data.push({ uri: aURI, title: aPageTitle, guid: aGUID });

Просмотреть файл

@ -20,14 +20,16 @@ add_task(async function test() {
PlacesUtils.history.markPageAsTyped(NetUtil.newURI(TEST_URL));
let promiseVisit = new Promise(resolve => {
function onVisits(events) {
PlacesObservers.removeListener(["page-visited"], onVisits);
is(events.length, 1, "Right number of visits");
is(events[0].type, "page-visited");
is(events[0].url, TEST_URL, "Check visited url");
resolve();
}
PlacesObservers.addListener(["page-visited"], onVisits);
let historyObserver = {
__proto__: NavHistoryObserver.prototype,
onVisits(visits) {
PlacesUtils.history.removeObserver(historyObserver);
is(visits.length, 1, "Right number of visits");
is(visits[0].uri.spec, TEST_URL, "Check visited url");
resolve();
}
};
PlacesUtils.history.addObserver(historyObserver);
});
gBrowser.selectedBrowser.loadURI(TEST_URL);
await promiseVisit;

Просмотреть файл

@ -77,6 +77,7 @@ function NavHistoryObserver() {}
NavHistoryObserver.prototype = {
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onVisits() {},
onTitleChanged() {},
onDeleteURI() {},
onClearHistory() {},

Просмотреть файл

@ -77,6 +77,7 @@ add_task(async function test_notifications_onDeleteURI() {
onBeginUpdateBatch: function PEX_onBeginUpdateBatch() {},
onEndUpdateBatch: function PEX_onEndUpdateBatch() {},
onClearHistory() {},
onVisits() {},
onTitleChanged() {},
onDeleteURI(aURI, aGUID, aReason) {
currentTest.receivedNotifications++;

Просмотреть файл

@ -102,6 +102,7 @@ add_task(async function test_notifications_onDeleteVisits() {
onBeginUpdateBatch: function PEX_onBeginUpdateBatch() {},
onEndUpdateBatch: function PEX_onEndUpdateBatch() {},
onClearHistory() {},
onVisits() {},
onTitleChanged() {},
onDeleteURI(aURI, aGUID, aReason) {
// Check this uri was not bookmarked.

Просмотреть файл

@ -734,6 +734,7 @@ function NavHistoryObserver() {}
NavHistoryObserver.prototype = {
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onVisits() {},
onTitleChanged() {},
onDeleteURI() {},
onClearHistory() {},

Просмотреть файл

@ -80,47 +80,48 @@ TitleChangedObserver.prototype = {
/**
* Listens for a visit notification, and calls aCallback when it gets it.
*
* @param aURI
* The URI of the page we expect a notification for.
* @param aCallback
* The method to call when we have gotten the proper notification about
* being visited.
*/
class VisitObserver {
constructor(aURI,
aGUID,
aCallback) {
this.uri = aURI;
this.guid = aGUID;
this.callback = aCallback;
this.handlePlacesEvent = this.handlePlacesEvent.bind(this);
PlacesObservers.addListener(["page-visited"], this.handlePlacesEvent);
}
handlePlacesEvent(aEvents) {
info("'page-visited'!!!");
Assert.equal(aEvents.length, 1, "Right number of visits notified");
Assert.equal(aEvents[0].type, "page-visited");
function VisitObserver(aURI,
aGUID,
aCallback) {
this.uri = aURI;
this.guid = aGUID;
this.callback = aCallback;
}
VisitObserver.prototype = {
__proto__: NavHistoryObserver.prototype,
onVisits(aVisits) {
info("onVisits()!!!");
Assert.equal(aVisits.length, 1, "Right number of visits notified");
let {
url,
uri,
visitId,
visitTime,
referringVisitId,
time,
referrerId,
transitionType,
pageGuid,
guid,
hidden,
visitCount,
typedCount,
typed,
lastKnownTitle,
} = aEvents[0];
} = aVisits[0];
let args = [
visitId, visitTime, referringVisitId, transitionType, pageGuid,
hidden, visitCount, typedCount, lastKnownTitle,
visitId, time, referrerId, transitionType, guid,
hidden, visitCount, typed, lastKnownTitle,
];
info("'page-visited' (" + url + args.join(", ") + ")");
if (this.uri.spec != url || this.guid != pageGuid) {
info("onVisit(" + uri.spec + args.join(", ") + ")");
if (!this.uri.equals(uri) || this.guid != guid) {
return;
}
this.callback(visitTime * 1000, transitionType, lastKnownTitle);
PlacesObservers.removeListener(["page-visited"], this.handlePlacesEvent);
}
}
this.callback(time, transitionType, lastKnownTitle);
},
};
/**
* Tests that a title was set properly in the database.
@ -983,15 +984,15 @@ add_task(async function test_title_change_notifies() {
});
let visitPromise = new Promise(resolve => {
function onVisits(events) {
Assert.equal(events.length, 1, "Should only get notified for one visit.");
Assert.equal(events[0].type, "page-visited");
let {url} = events[0];
Assert.equal(url, place.uri.spec, "Should get notified for visiting the new URI.");
PlacesObservers.removeListener(["page-visited"], onVisits);
resolve();
}
PlacesObservers.addListener(["page-visited"], onVisits);
PlacesUtils.history.addObserver({
onVisits(visits) {
Assert.equal(visits.length, 1, "Should only get notified for one visit.");
let {uri} = visits[0];
Assert.equal(uri.spec, place.uri.spec, "Should get notified for visiting the new URI.");
PlacesUtils.history.removeObserver(this);
resolve();
}
});
});
asyncHistory.updatePlaces(place);
await visitPromise;
@ -1027,15 +1028,17 @@ add_task(async function test_visit_notifies() {
resolve();
}
};
new VisitObserver(place.uri, place.guid,
let visitObserver = new VisitObserver(place.uri, place.guid,
function(aVisitDate,
aTransitionType) {
let visit = place.visits[0];
Assert.equal(visit.visitDate, aVisitDate);
Assert.equal(visit.transitionType, aTransitionType);
PlacesUtils.history.removeObserver(visitObserver);
finisher();
});
PlacesUtils.history.addObserver(visitObserver);
let observer = function(aSubject, aTopic, aData) {
info("observe(" + aSubject + ", " + aTopic + ", " + aData + ")");
Assert.ok(aSubject instanceof Ci.nsIURI);
@ -1266,14 +1269,16 @@ add_task(async function test_title_on_initial_visit() {
guid: "mnopqrstuvwx",
};
let visitPromise = new Promise(resolve => {
new VisitObserver(place.uri, place.guid,
function(aVisitDate,
aTransitionType,
aLastKnownTitle) {
let visitObserver = new VisitObserver(place.uri, place.guid,
function(aVisitDate,
aTransitionType,
aLastKnownTitle) {
Assert.equal(place.title, aLastKnownTitle);
PlacesUtils.history.removeObserver(visitObserver);
resolve();
});
PlacesUtils.history.addObserver(visitObserver);
});
await promiseUpdatePlaces(place);
await visitPromise;
@ -1288,14 +1293,16 @@ add_task(async function test_title_on_initial_visit() {
guid: "fghijklmnopq",
};
visitPromise = new Promise(resolve => {
new VisitObserver(place.uri, place.guid,
function(aVisitDate,
aTransitionType,
aLastKnownTitle) {
let visitObserver = new VisitObserver(place.uri, place.guid,
function(aVisitDate,
aTransitionType,
aLastKnownTitle) {
Assert.equal(place.title, aLastKnownTitle);
PlacesUtils.history.removeObserver(visitObserver);
resolve();
});
PlacesUtils.history.addObserver(visitObserver);
});
await promiseUpdatePlaces(place);
await visitPromise;
@ -1309,14 +1316,16 @@ add_task(async function test_title_on_initial_visit() {
guid: "fghijklmnopq",
};
visitPromise = new Promise(resolve => {
new VisitObserver(place.uri, place.guid,
function(aVisitDate,
aTransitionType,
aLastKnownTitle) {
let visitObserver = new VisitObserver(place.uri, place.guid,
function(aVisitDate,
aTransitionType,
aLastKnownTitle) {
Assert.equal(null, aLastKnownTitle);
PlacesUtils.history.removeObserver(visitObserver);
resolve();
});
PlacesUtils.history.addObserver(visitObserver);
});
await promiseUpdatePlaces(place);
await visitPromise;

Просмотреть файл

@ -44,6 +44,9 @@ add_task(async function test_remove_single() {
observer = {
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onVisits(aVisits) {
reject(new Error("Unexpected call to onVisits " + aVisits.length));
},
onTitleChanged(aUri) {
reject(new Error("Unexpected call to onTitleChanged " + aUri.spec));
},

Просмотреть файл

@ -292,6 +292,9 @@ function getObserverPromise(bookmarkedUri) {
observer = {
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onVisits() {
reject(new Error("Unexpected call to onVisits"));
},
onTitleChanged(aUri) {
reject(new Error("Unexpected call to onTitleChanged"));
},

Просмотреть файл

@ -134,6 +134,9 @@ add_task(async function test_removeVisitsByFilter() {
deferred: PromiseUtils.defer(),
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onVisits(aVisits) {
this.deferred.reject(new Error("Unexpected call to onVisits " + aVisits.length));
},
onTitleChanged(uri) {
this.deferred.reject(new Error("Unexpected call to onTitleChanged " + uri.spec));
},

Просмотреть файл

@ -11,11 +11,11 @@ var visit_count = 0;
async function task_add_visit(aURI, aVisitType) {
// Wait for a visits notification and get the visitId.
let visitId;
let visitsPromise = PlacesTestUtils.waitForNotification("page-visited", visits => {
let visitsPromise = PlacesTestUtils.waitForNotification("onVisits", visits => {
visitId = visits[0].visitId;
let {url} = visits[0];
return url == aURI.spec;
}, "places");
let {uri} = visits[0];
return uri.equals(aURI);
}, "history");
// Add visits.
await PlacesTestUtils.addVisits([{

Просмотреть файл

@ -20,28 +20,29 @@ const PRIVATE_URI = NetUtil.newURI("http://www.example.net/");
* Callback function to be called with the same arguments of onVisit.
*/
function waitForOnVisit(aCallback) {
function listener(aEvents) {
Assert.equal(aEvents.length, 1, "Right number of visits notified");
Assert.equal(aEvents[0].type, "page-visited");
let {
url,
visitId,
visitTime,
referringVisitId,
transitionType,
pageGuid,
hidden,
visitCount,
typedCount,
lastKnownTitle,
} = aEvents[0];
PlacesObservers.removeListener(["page-visited"], listener);
let uriArg = NetUtil.newURI(url);
aCallback(uriArg, visitId, visitTime, 0, referringVisitId,
transitionType, pageGuid, hidden, visitCount,
typedCount, lastKnownTitle);
}
PlacesObservers.addListener(["page-visited"], listener);
let historyObserver = {
__proto__: NavHistoryObserver.prototype,
onVisits: function HO_onVisit(aVisits) {
Assert.equal(aVisits.length, 1, "Right number of visits notified");
let {
uri,
visitId,
time,
referrerId,
transitionType,
guid,
hidden,
visitCount,
typed,
lastKnownTitle,
} = aVisits[0];
PlacesUtils.history.removeObserver(this);
aCallback(uri, visitId, time, 0, referrerId,
transitionType, guid, hidden, visitCount,
typed, lastKnownTitle);
}
};
PlacesUtils.history.addObserver(historyObserver);
}
/**
@ -156,11 +157,11 @@ add_task(async function test_dh_addBookmarkRemoveDownload() {
add_task(async function test_dh_addDownload_referrer() {
// Wait for visits notification and get the visit id.
let visitId;
let referrerPromise = PlacesTestUtils.waitForNotification("page-visited", visits => {
let referrerPromise = PlacesTestUtils.waitForNotification("onVisits", visits => {
visitId = visits[0].visitId;
let {url} = visits[0];
return url == REFERRER_URI.spec;
}, "places");
let {uri} = visits[0];
return uri.equals(REFERRER_URI);
}, "history");
await PlacesTestUtils.addVisits([{
uri: REFERRER_URI,
@ -174,17 +175,16 @@ add_task(async function test_dh_addDownload_referrer() {
// Wait for visits notification and get the referrer Id.
let referrerId;
let downloadPromise = PlacesTestUtils.waitForNotification("page-visited", visits => {
referrerId = visits[0].referringVisitId;
let {url} = visits[0];
return url == DOWNLOAD_URI.spec;
}, "places");
let downloadPromise = PlacesTestUtils.waitForNotification("onVisits", visits => {
referrerId = visits[0].referrerId;
let {uri} = visits[0];
return uri.equals(DOWNLOAD_URI);
}, "history");
gDownloadHistory.addDownload(DOWNLOAD_URI, REFERRER_URI, Date.now() * 1000);
await downloadPromise;
// Verify results for download uri.
// ensure that we receive the 'page-visited' notification before we call addDownload.
Assert.ok(!!PlacesTestUtils.isPageInDB(DOWNLOAD_URI));
Assert.equal(visitId, referrerId);
@ -260,6 +260,7 @@ add_test(function test_dh_details() {
let historyObserver = {
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onVisits() {},
onTitleChanged: function HO_onTitleChanged(aURI, aPageTitle) {
if (aURI.equals(SOURCE_URI)) {
titleSet = true;

Просмотреть файл

@ -10,6 +10,7 @@ function NavHistoryObserver() {
NavHistoryObserver.prototype = {
onBeginUpdateBatch() { },
onEndUpdateBatch() { },
onVisits() { },
onTitleChanged() { },
onDeleteURI() { },
onClearHistory() { },
@ -35,23 +36,6 @@ function onNotify(callback) {
});
}
/**
* Registers a one-time places observer for 'page-visited',
* which resolves a promise on being called.
*/
function promiseVisitAdded(callback) {
return new Promise(resolve => {
function listener(events) {
PlacesObservers.removeListener(["page-visited"], listener);
Assert.equal(events.length, 1, "Right number of visits notified");
Assert.equal(events[0].type, "page-visited");
callback(events[0]);
resolve();
}
PlacesObservers.addListener(["page-visited"], listener);
});
}
/**
* Asynchronous task that adds a visit to the history database.
*/
@ -66,18 +50,19 @@ async function task_add_visit(uri, timestamp, transition) {
return [uri, timestamp];
}
add_task(async function test_visitAdded() {
let promiseNotify = promiseVisitAdded(function(visit) {
add_task(async function test_onVisits() {
let promiseNotify = onNotify(function onVisits(aVisits) {
Assert.equal(aVisits.length, 1, "Right number of visits notified");
let visit = aVisits[0];
Assert.ok(visit.uri.equals(testuri));
Assert.ok(visit.visitId > 0);
Assert.equal(visit.url, testuri.spec);
Assert.equal(visit.visitTime, testtime / 1000);
Assert.equal(visit.referringVisitId, 0);
Assert.equal(visit.time, testtime);
Assert.equal(visit.referrerId, 0);
Assert.equal(visit.transitionType, TRANSITION_TYPED);
let uri = NetUtil.newURI(visit.url);
do_check_guid_for_uri(uri, visit.pageGuid);
do_check_guid_for_uri(visit.uri, visit.guid);
Assert.ok(!visit.hidden);
Assert.equal(visit.visitCount, 1);
Assert.equal(visit.typedCount, 1);
Assert.equal(visit.typed, 1);
});
let testuri = NetUtil.newURI("http://firefox.com/");
let testtime = Date.now() * 1000;
@ -85,18 +70,19 @@ add_task(async function test_visitAdded() {
await promiseNotify;
});
add_task(async function test_visitAdded() {
let promiseNotify = promiseVisitAdded(function(visit) {
add_task(async function test_onVisits() {
let promiseNotify = onNotify(function onVisits(aVisits) {
Assert.equal(aVisits.length, 1, "Right number of visits notified");
let visit = aVisits[0];
Assert.ok(visit.uri.equals(testuri));
Assert.ok(visit.visitId > 0);
Assert.equal(visit.url, testuri.spec);
Assert.equal(visit.visitTime, testtime / 1000);
Assert.equal(visit.referringVisitId, 0);
Assert.equal(visit.time, testtime);
Assert.equal(visit.referrerId, 0);
Assert.equal(visit.transitionType, TRANSITION_FRAMED_LINK);
let uri = NetUtil.newURI(visit.url);
do_check_guid_for_uri(uri, visit.pageGuid);
do_check_guid_for_uri(visit.uri, visit.guid);
Assert.ok(visit.hidden);
Assert.equal(visit.visitCount, 1);
Assert.equal(visit.typedCount, 0);
Assert.equal(visit.typed, 0);
});
let testuri = NetUtil.newURI("http://hidden.firefox.com/");
let testtime = Date.now() * 1000;
@ -107,43 +93,44 @@ add_task(async function test_visitAdded() {
add_task(async function test_multiple_onVisit() {
let testuri = NetUtil.newURI("http://self.firefox.com/");
let promiseNotifications = new Promise(resolve => {
function listener(aEvents) {
Assert.equal(aEvents.length, 3, "Right number of visits notified");
for (let i = 0; i < aEvents.length; i++) {
Assert.equal(aEvents[i].type, "page-visited");
let visit = aEvents[i];
Assert.equal(testuri.spec, visit.url);
Assert.ok(visit.visitId > 0);
Assert.ok(visit.visitTime > 0);
Assert.ok(!visit.hidden);
let uri = NetUtil.newURI(visit.url);
do_check_guid_for_uri(uri, visit.pageGuid);
switch (i) {
case 0:
Assert.equal(visit.referringVisitId, 0);
Assert.equal(visit.transitionType, TRANSITION_LINK);
Assert.equal(visit.visitCount, 1);
Assert.equal(visit.typedCount, 0);
break;
case 1:
Assert.ok(visit.referringVisitId > 0);
Assert.equal(visit.transitionType, TRANSITION_LINK);
Assert.equal(visit.visitCount, 2);
Assert.equal(visit.typedCount, 0);
break;
case 2:
Assert.equal(visit.referringVisitId, 0);
Assert.equal(visit.transitionType, TRANSITION_TYPED);
Assert.equal(visit.visitCount, 3);
Assert.equal(visit.typedCount, 1);
let observer = {
__proto__: NavHistoryObserver.prototype,
onVisits(aVisits) {
Assert.equal(aVisits.length, 3, "Right number of visits notified");
for (let i = 0; i < aVisits.length; i++) {
let visit = aVisits[i];
Assert.ok(testuri.equals(visit.uri));
Assert.ok(visit.visitId > 0);
Assert.ok(visit.time > 0);
Assert.ok(!visit.hidden);
do_check_guid_for_uri(visit.uri, visit.guid);
switch (i) {
case 0:
Assert.equal(visit.referrerId, 0);
Assert.equal(visit.transitionType, TRANSITION_LINK);
Assert.equal(visit.visitCount, 1);
Assert.equal(visit.typed, 0);
break;
case 1:
Assert.ok(visit.referrerId > 0);
Assert.equal(visit.transitionType, TRANSITION_LINK);
Assert.equal(visit.visitCount, 2);
Assert.equal(visit.typed, 0);
break;
case 2:
Assert.equal(visit.referrerId, 0);
Assert.equal(visit.transitionType, TRANSITION_TYPED);
Assert.equal(visit.visitCount, 3);
Assert.equal(visit.typed, 1);
PlacesObservers.removeListener(["page-visited"], listener);
resolve();
break;
PlacesUtils.history.removeObserver(observer, false);
resolve();
break;
}
}
}
}
PlacesObservers.addListener(["page-visited"], listener);
},
};
PlacesUtils.history.addObserver(observer);
});
await PlacesTestUtils.addVisits([
{ uri: testuri, transition: TRANSITION_LINK },

Просмотреть файл

@ -12,24 +12,43 @@ var gVisits = [{url: "http://www.mozilla.com/",
transition: TRANSITION_LINK}];
add_task(async function test_execute() {
let observer;
let completionPromise = new Promise(resolveCompletionPromise => {
let visitCount = 0;
function listener(aEvents) {
Assert.equal(aEvents.length, 1, "Right number of visits notified");
Assert.equal(aEvents[0].type, "page-visited");
let event = aEvents[0];
Assert.equal(event.url, gVisits[visitCount].url);
Assert.equal(event.transitionType, gVisits[visitCount].transition);
visitCount++;
observer = {
__proto__: NavHistoryObserver.prototype,
_visitCount: 0,
onVisit(aURI, aVisitID, aTime, aSessionID, aReferringID,
aTransitionType, aAdded) {
Assert.equal(aURI.spec, gVisits[this._visitCount].url);
Assert.equal(aTransitionType, gVisits[this._visitCount].transition);
this._visitCount++;
if (visitCount == gVisits.length) {
resolveCompletionPromise();
PlacesObservers.removeListener(["page-visited"], listener);
}
}
PlacesObservers.addListener(["page-visited"], listener);
if (this._visitCount == gVisits.length) {
resolveCompletionPromise();
}
},
onVisits(aVisits) {
Assert.equal(aVisits.length, 1, "Right number of visits notified");
let {
uri,
visitId,
time,
referrerId,
transitionType,
guid,
hidden,
visitCount,
typed,
lastKnownTitle,
} = aVisits[0];
this.onVisit(uri, visitId, time, 0, referrerId,
transitionType, guid, hidden, visitCount,
typed, lastKnownTitle);
},
};
});
PlacesUtils.history.addObserver(observer);
for (var visit of gVisits) {
if (visit.transition == TRANSITION_TYPED)
@ -48,4 +67,5 @@ add_task(async function test_execute() {
await completionPromise;
PlacesUtils.history.removeObserver(observer);
});

Просмотреть файл

@ -827,6 +827,7 @@ var PageThumbsHistoryObserver = {
onTitleChanged() {},
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onVisits() {},
onPageChanged() {},
onDeleteVisits() {},

Просмотреть файл

@ -549,9 +549,6 @@ var PlacesProvider = {
*/
init: function PlacesProvider_init() {
PlacesUtils.history.addObserver(this, true);
this._placesObserver =
new PlacesWeakCallbackWrapper(this.handlePlacesEvents.bind(this));
PlacesObservers.addListener(["page-visited"], this._placesObserver);
},
/**
@ -659,11 +656,11 @@ var PlacesProvider = {
}
},
handlePlacesEvents(aEvents) {
onVisits(aVisits) {
if (!this._batchProcessingDepth) {
for (let event of aEvents) {
if (event.visitCount == 1 && event.lastKnownTitle) {
this.onTitleChanged(event.url, event.lastKnownTitle, event.pageGuid);
for (let visit of aVisits) {
if (visit.visitCount == 1 && visit.lastKnownTitle) {
this.onTitleChanged(visit.uri, visit.lastKnownTitle, visit.guid);
}
}
}
@ -714,11 +711,8 @@ var PlacesProvider = {
* Called by the history service.
*/
onTitleChanged: function PlacesProvider_onTitleChanged(aURI, aNewTitle, aGUID) {
if (aURI instanceof Ci.nsIURI) {
aURI = aURI.spec;
}
this._callObservers("onLinkChanged", {
url: aURI,
url: aURI.spec,
title: aNewTitle
});
},

Просмотреть файл

@ -41,9 +41,6 @@ module.exports = {
"MatchPatternSet": false,
"MenuBoxObject": false,
// Specific to Firefox (Chrome code only).
"PlacesObservers": false,
"PlacesWeakCallbackWrapper": false,
// Specific to Firefox (Chrome code only).
"SharedArrayBuffer": false,
"SimpleGestureEvent": false,
// Note: StopIteration will likely be removed as part of removing legacy