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:
Doug Thayer 2018-02-14 09:06:15 -08:00
Родитель 8d49b70679
Коммит 120468d5fd
15 изменённых файлов: 836 добавлений и 188 удалений

52
dom/base/PlacesEvent.cpp Normal file
Просмотреть файл

@ -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

48
dom/base/PlacesEvent.h Normal file
Просмотреть файл

@ -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__

67
dom/base/PlacesVisit.h Normal file
Просмотреть файл

@ -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