зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1340498 - Implement new Places Observers interface r=mrbkap
See the design doc[1] for further info. We would like to redesign the places observer system to be more performant and more friendly to consume. WebIDL was recommended as it simplifies creating simple dictionary payloads while allowing dynamic typing with `any`. There were some difficulties with WebIDL though, most of which revolved around allowing consumers to be weakly referenced, from both C++ and JS. The simplest solution I could come up with was to create a simple native interface for the C++ case, and a WebIDL wrapper for a JS callback in the JS case. Suggestions for simpler alternatives are very welcome though. [1] https://docs.google.com/document/d/1G45vfd6RXFXwNz7i4FV40lDCU0ao-JX_bZdgJV4tLjk/edit?usp=sharing MozReview-Commit-ID: ACnAEfa5WxO --HG-- extra : rebase_source : cb13b24696ee97b611c318b407ea9c31215df3f6
This commit is contained in:
Родитель
8d49b70679
Коммит
120468d5fd
|
@ -0,0 +1,52 @@
|
|||
/* -*- 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
|
|
@ -0,0 +1,48 @@
|
|||
/* -*- 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
|
|
@ -0,0 +1,350 @@
|
|||
/* -*- 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
|
|
@ -0,0 +1,62 @@
|
|||
/* -*- 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__
|
|
@ -0,0 +1,67 @@
|
|||
/* -*- 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
|
|
@ -0,0 +1,55 @@
|
|||
/* -*- 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
|
|
@ -0,0 +1,49 @@
|
|||
/* -*- 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
|
|
@ -201,6 +201,10 @@ EXPORTS.mozilla.dom += [
|
|||
'NodeInfoInlines.h',
|
||||
'NodeIterator.h',
|
||||
'ParentProcessMessageManager.h',
|
||||
'PlacesEvent.h',
|
||||
'PlacesObservers.h',
|
||||
'PlacesVisit.h',
|
||||
'PlacesWeakCallbackWrapper.h',
|
||||
'Pose.h',
|
||||
'ProcessGlobal.h',
|
||||
'ProcessMessageManager.h',
|
||||
|
@ -390,6 +394,13 @@ 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.
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
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;
|
||||
};
|
|
@ -0,0 +1,32 @@
|
|||
/* -*- 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,3 +46,9 @@ WEBIDL_FILES = [
|
|||
'WebExtensionContentScript.webidl',
|
||||
'WebExtensionPolicy.webidl',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_PLACES']:
|
||||
WEBIDL_FILES += [
|
||||
'PlacesEvent.webidl',
|
||||
'PlacesObservers.webidl',
|
||||
]
|
||||
|
|
|
@ -169,121 +169,6 @@ 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
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/* -*- 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
|
|
@ -29,6 +29,7 @@ if CONFIG['MOZ_PLACES']:
|
|||
EXPORTS.mozilla.places = [
|
||||
'Database.h',
|
||||
'History.h',
|
||||
'INativePlacesEventCallback.h',
|
||||
'Shutdown.h',
|
||||
]
|
||||
|
||||
|
|
|
@ -29,67 +29,6 @@ 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
|
||||
{
|
||||
|
@ -642,18 +581,6 @@ 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
|
||||
|
|
Загрузка…
Ссылка в новой задаче