зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1615403 - Part 1: Introduce a new MaybeDiscarded type, r=farre
Adds a new MaybeDiscarded wrapper type which allows sending a maybe-discarded BrowsingContext over IPC to another process which must be explicitly checked for nullness and discarded status before being used. Differential Revision: https://phabricator.services.mozilla.com/D62832 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
0d667d17dd
Коммит
77393e07dd
|
@ -1516,6 +1516,33 @@ void BrowsingContext::AddDeprioritizedLoadRunner(nsIRunnable* aRunner) {
|
|||
|
||||
namespace ipc {
|
||||
|
||||
void IPDLParamTraits<dom::MaybeDiscarded<dom::BrowsingContext>>::Write(
|
||||
IPC::Message* aMsg, IProtocol* aActor,
|
||||
const dom::MaybeDiscarded<dom::BrowsingContext>& aParam) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(!aParam.GetMaybeDiscarded() ||
|
||||
aParam.GetMaybeDiscarded()->EverAttached());
|
||||
uint64_t id = aParam.ContextId();
|
||||
WriteIPDLParam(aMsg, aActor, id);
|
||||
}
|
||||
|
||||
bool IPDLParamTraits<dom::MaybeDiscarded<dom::BrowsingContext>>::Read(
|
||||
const IPC::Message* aMsg, PickleIterator* aIter, IProtocol* aActor,
|
||||
dom::MaybeDiscarded<dom::BrowsingContext>* aResult) {
|
||||
uint64_t id = 0;
|
||||
if (!ReadIPDLParam(aMsg, aIter, aActor, &id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (id == 0) {
|
||||
*aResult = nullptr;
|
||||
} else if (RefPtr<dom::BrowsingContext> bc = dom::BrowsingContext::Get(id)) {
|
||||
*aResult = std::move(bc);
|
||||
} else {
|
||||
aResult->SetDiscarded(id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void IPDLParamTraits<dom::BrowsingContext*>::Write(
|
||||
IPC::Message* aMsg, IProtocol* aActor, dom::BrowsingContext* aParam) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(!aParam || aParam->EverAttached());
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/LoadURIOptionsBinding.h"
|
||||
#include "mozilla/dom/LocationBase.h"
|
||||
#include "mozilla/dom/MaybeDiscarded.h"
|
||||
#include "mozilla/dom/FeaturePolicyUtils.h"
|
||||
#include "mozilla/dom/SessionStorageManager.h"
|
||||
#include "mozilla/dom/UserActivation.h"
|
||||
|
@ -730,6 +731,7 @@ extern bool GetRemoteOuterWindowProxy(JSContext* aCx, BrowsingContext* aContext,
|
|||
using BrowsingContextTransaction = BrowsingContext::BaseTransaction;
|
||||
using BrowsingContextInitializer = BrowsingContext::IPCInitializer;
|
||||
using BrowsingContextChildren = BrowsingContext::Children;
|
||||
using MaybeDiscardedBrowsingContext = MaybeDiscarded<BrowsingContext>;
|
||||
|
||||
// Specialize the transaction object for every translation unit it's used in.
|
||||
extern template class syncedcontext::Transaction<BrowsingContext>;
|
||||
|
@ -738,6 +740,15 @@ extern template class syncedcontext::Transaction<BrowsingContext>;
|
|||
|
||||
// Allow sending BrowsingContext objects over IPC.
|
||||
namespace ipc {
|
||||
template <>
|
||||
struct IPDLParamTraits<dom::MaybeDiscarded<dom::BrowsingContext>> {
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
const dom::MaybeDiscarded<dom::BrowsingContext>& aParam);
|
||||
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
IProtocol* aActor,
|
||||
dom::MaybeDiscarded<dom::BrowsingContext>* aResult);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IPDLParamTraits<dom::BrowsingContext*> {
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#ifndef mozilla_dom_SyncedContext_h
|
||||
#define mozilla_dom_SyncedContext_h
|
||||
|
||||
#include "mozilla/dom/MaybeDiscarded.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/Tuple.h"
|
||||
|
|
|
@ -40,6 +40,11 @@ BrowsingContextGroup* WindowContext::Group() const {
|
|||
return mBrowsingContext->Group();
|
||||
}
|
||||
|
||||
WindowGlobalParent* WindowContext::Canonical() {
|
||||
MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
|
||||
return static_cast<WindowGlobalParent*>(this);
|
||||
}
|
||||
|
||||
nsIGlobalObject* WindowContext::GetParentObject() const {
|
||||
return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
|
||||
}
|
||||
|
@ -168,6 +173,31 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(WindowContext)
|
|||
|
||||
namespace ipc {
|
||||
|
||||
void IPDLParamTraits<dom::MaybeDiscarded<dom::WindowContext>>::Write(
|
||||
IPC::Message* aMsg, IProtocol* aActor,
|
||||
const dom::MaybeDiscarded<dom::WindowContext>& aParam) {
|
||||
uint64_t id = aParam.ContextId();
|
||||
WriteIPDLParam(aMsg, aActor, id);
|
||||
}
|
||||
|
||||
bool IPDLParamTraits<dom::MaybeDiscarded<dom::WindowContext>>::Read(
|
||||
const IPC::Message* aMsg, PickleIterator* aIter, IProtocol* aActor,
|
||||
dom::MaybeDiscarded<dom::WindowContext>* aResult) {
|
||||
uint64_t id = 0;
|
||||
if (!ReadIPDLParam(aMsg, aIter, aActor, &id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (id == 0) {
|
||||
*aResult = nullptr;
|
||||
} else if (RefPtr<dom::WindowContext> wc = dom::WindowContext::GetById(id)) {
|
||||
*aResult = std::move(wc);
|
||||
} else {
|
||||
aResult->SetDiscarded(id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void IPDLParamTraits<dom::WindowContext*>::Write(IPC::Message* aMsg,
|
||||
IProtocol* aActor,
|
||||
dom::WindowContext* aParam) {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#ifndef mozilla_dom_WindowContext_h
|
||||
#define mozilla_dom_WindowContext_h
|
||||
|
||||
#include "mozilla/dom/MaybeDiscarded.h"
|
||||
#include "mozilla/dom/SyncedContext.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -26,9 +27,13 @@ class WindowContext : public nsISupports, public nsWrapperCache {
|
|||
|
||||
BrowsingContext* GetBrowsingContext() const { return mBrowsingContext; }
|
||||
BrowsingContextGroup* Group() const;
|
||||
uint64_t Id() const { return InnerWindowId(); }
|
||||
uint64_t InnerWindowId() const { return mInnerWindowId; }
|
||||
bool IsDiscarded() const { return mIsDiscarded; }
|
||||
|
||||
// Cast this object to it's parent-process canonical form.
|
||||
WindowGlobalParent* Canonical();
|
||||
|
||||
nsIGlobalObject* GetParentObject() const;
|
||||
JSObject* WrapObject(JSContext* cx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
@ -80,6 +85,7 @@ class WindowContext : public nsISupports, public nsWrapperCache {
|
|||
|
||||
using WindowContextTransaction = WindowContext::BaseTransaction;
|
||||
using WindowContextInitializer = WindowContext::IPCInitializer;
|
||||
using MaybeDiscardedWindowContext = MaybeDiscarded<WindowContext>;
|
||||
|
||||
// Don't specialize the `Transaction` object for every translation unit it's
|
||||
// used in. This should help keep code size down.
|
||||
|
@ -88,6 +94,15 @@ extern template class syncedcontext::Transaction<WindowContext>;
|
|||
} // namespace dom
|
||||
|
||||
namespace ipc {
|
||||
template <>
|
||||
struct IPDLParamTraits<dom::MaybeDiscarded<dom::WindowContext>> {
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
const dom::MaybeDiscarded<dom::WindowContext>& aParam);
|
||||
static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
|
||||
IProtocol* aActor,
|
||||
dom::MaybeDiscarded<dom::WindowContext>* aResult);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IPDLParamTraits<dom::WindowContext*> {
|
||||
static void Write(IPC::Message* aMsg, IProtocol* aActor,
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
/* -*- 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_MaybeDiscarded_h
|
||||
#define mozilla_dom_MaybeDiscarded_h
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// Wrapper type for a WindowContext or BrowsingContext instance which may be
|
||||
// discarded, and thus unavailable in the current process. This type is used to
|
||||
// pass WindowContext and BrowsingContext instances over IPC, as they may be
|
||||
// discarded in the receiving process.
|
||||
//
|
||||
// A MaybeDiscarded can generally be implicitly converted to from a
|
||||
// BrowsingContext* or WindowContext*, but requires an explicit check of
|
||||
// |IsDiscarded| and call to |get| to read from.
|
||||
template <typename T>
|
||||
class MaybeDiscarded {
|
||||
public:
|
||||
MaybeDiscarded() = default;
|
||||
MaybeDiscarded(MaybeDiscarded<T>&&) = default;
|
||||
MaybeDiscarded(const MaybeDiscarded<T>&) = default;
|
||||
|
||||
// Construct from raw pointers and |nullptr|.
|
||||
MOZ_IMPLICIT MaybeDiscarded(T* aRawPtr)
|
||||
: mId(aRawPtr ? aRawPtr->Id() : 0), mPtr(aRawPtr) {}
|
||||
MOZ_IMPLICIT MaybeDiscarded(decltype(nullptr)) {}
|
||||
|
||||
// Construct from |RefPtr<I>|
|
||||
template <typename I,
|
||||
typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
|
||||
MOZ_IMPLICIT MaybeDiscarded(RefPtr<I>&& aPtr)
|
||||
: mId(aPtr ? aPtr->Id() : 0), mPtr(std::move(aPtr)) {}
|
||||
template <typename I,
|
||||
typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
|
||||
MOZ_IMPLICIT MaybeDiscarded(const RefPtr<I>& aPtr)
|
||||
: mId(aPtr ? aPtr->Id() : 0), mPtr(aPtr) {}
|
||||
|
||||
// Basic assignment operators.
|
||||
MaybeDiscarded<T>& operator=(const MaybeDiscarded<T>&) = default;
|
||||
MaybeDiscarded<T>& operator=(MaybeDiscarded<T>&&) = default;
|
||||
MaybeDiscarded<T>& operator=(decltype(nullptr)) {
|
||||
mId = 0;
|
||||
mPtr = nullptr;
|
||||
return *this;
|
||||
}
|
||||
MaybeDiscarded<T>& operator=(T* aRawPtr) {
|
||||
mId = aRawPtr ? aRawPtr->Id() : 0;
|
||||
mPtr = aRawPtr;
|
||||
return *this;
|
||||
}
|
||||
template <typename I>
|
||||
MaybeDiscarded<T>& operator=(const RefPtr<I>& aRhs) {
|
||||
mId = aRhs ? aRhs->Id() : 0;
|
||||
mPtr = aRhs;
|
||||
return *this;
|
||||
}
|
||||
template <typename I>
|
||||
MaybeDiscarded<T>& operator=(RefPtr<I>&& aRhs) {
|
||||
mId = aRhs ? aRhs->Id() : 0;
|
||||
mPtr = std::move(aRhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Validate that the value is neither discarded nor null.
|
||||
bool IsNullOrDiscarded() const { return !mPtr || mPtr->IsDiscarded(); }
|
||||
bool IsDiscarded() const { return IsNullOrDiscarded() && !IsNull(); }
|
||||
bool IsNull() const { return mId == 0; }
|
||||
|
||||
// Extract the wrapped |T|. Must not be called on a discarded |T|.
|
||||
T* get() const {
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsDiscarded());
|
||||
return mPtr.get();
|
||||
}
|
||||
already_AddRefed<T> forget() {
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsDiscarded());
|
||||
return mPtr.forget();
|
||||
}
|
||||
|
||||
// Like "get", but gets the "Canonical" version of the type. This method may
|
||||
// only be called in the parent process.
|
||||
auto get_canonical() const -> decltype(get()->Canonical()) {
|
||||
if (get()) {
|
||||
return get()->Canonical();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// The ID for the context wrapped by this MaybeDiscarded. This ID comes from a
|
||||
// remote process, and should generally only be used for logging. A
|
||||
// BrowsingContext with this ID may not exist in the current process.
|
||||
uint64_t ContextId() const { return mId; }
|
||||
|
||||
// Tries to get the wrapped value, disregarding discarded status.
|
||||
// This may return |nullptr| for a non-null |MaybeDiscarded|, in the case that
|
||||
// the target is no longer available in this process.
|
||||
T* GetMaybeDiscarded() const { return mPtr.get(); }
|
||||
|
||||
// Clear the value to a discarded state with the given ID.
|
||||
void SetDiscarded(uint64_t aId) {
|
||||
mId = aId;
|
||||
mPtr = nullptr;
|
||||
}
|
||||
|
||||
// Comparison operators required by IPDL
|
||||
bool operator==(const MaybeDiscarded<T>& aRhs) const {
|
||||
return mId == aRhs.mId && mPtr == aRhs.mPtr;
|
||||
}
|
||||
bool operator!=(const MaybeDiscarded<T>& aRhs) const {
|
||||
return !operator==(aRhs);
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t mId = 0;
|
||||
RefPtr<T> mPtr;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_MaybeDiscarded_h
|
|
@ -57,6 +57,7 @@ EXPORTS.mozilla.dom += [
|
|||
'JSWindowActorChild.h',
|
||||
'JSWindowActorParent.h',
|
||||
'JSWindowActorService.h',
|
||||
'MaybeDiscarded.h',
|
||||
'MemoryReportRequest.h',
|
||||
'PermissionMessageUtils.h',
|
||||
'PropertyBagUtils.h',
|
||||
|
|
Загрузка…
Ссылка в новой задаче