Bug 1487463 - implement StructuredCloneTester to be used in testing r=baku

StructuredCloneTester objects can configured to be serializable (or not) and
deserializable (or not) by the structured clone algorithm. They can be used to
test, for example, onmessageerror event handlers, where the messageerror event
is fired when a message fails to be deserialized (but was successfully serialized).
The class is pref'ed with "dom.testing.structuredclonetester.enabled".

Differential Revision: https://phabricator.services.mozilla.com/D5207

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Perry Jiang 2018-10-02 16:43:57 +00:00
Родитель 9c05614e43
Коммит fd4ce6d9d5
9 изменённых файлов: 242 добавлений и 1 удалений

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

@ -20,6 +20,7 @@ DOM_WEBIDL_PREF(dom_webnotifications_serviceworker_enabled)
DOM_WEBIDL_PREF(dom_webnotifications_requireinteraction_enabled)
DOM_WEBIDL_PREF(dom_serviceWorkers_enabled)
DOM_WEBIDL_PREF(dom_storageManager_enabled)
DOM_WEBIDL_PREF(dom_testing_structuredclonetester_enabled)
DOM_WEBIDL_PREF(dom_promise_rejection_events_enabled)
DOM_WEBIDL_PREF(dom_push_enabled)
DOM_WEBIDL_PREF(gfx_offscreencanvas_enabled)

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

@ -13,6 +13,7 @@
#include "mozilla/dom/StructuredCloneBlob.h"
#include "mozilla/dom/Directory.h"
#include "mozilla/dom/DirectoryBinding.h"
#include "mozilla/dom/DOMPrefs.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FileList.h"
#include "mozilla/dom/FileListBinding.h"
@ -28,6 +29,8 @@
#include "mozilla/dom/OffscreenCanvasBinding.h"
#include "mozilla/dom/PMessagePort.h"
#include "mozilla/dom/StructuredCloneTags.h"
#include "mozilla/dom/StructuredCloneTester.h"
#include "mozilla/dom/StructuredCloneTesterBinding.h"
#include "mozilla/dom/SubtleCryptoBinding.h"
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/dom/URLSearchParams.h"
@ -455,6 +458,10 @@ StructuredCloneHolder::ReadFullySerializableObjects(JSContext* aCx,
}
#endif
if (aTag == SCTAG_DOM_STRUCTURED_CLONE_TESTER) {
return StructuredCloneTester::ReadStructuredClone(aCx, aReader);
}
// Don't know what this is. Bail.
xpc::Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
return nullptr;
@ -505,6 +512,22 @@ StructuredCloneHolder::WriteFullySerializableObjects(JSContext* aCx,
}
#endif
// StructuredCloneTester - testing only
{
StructuredCloneTester* sct = nullptr;
if (NS_SUCCEEDED(UNWRAP_OBJECT(StructuredCloneTester, &obj, sct))) {
MOZ_ASSERT(StaticPrefs::dom_testing_structuredclonetester_enabled());
// "Fail" serialization
if (!sct->Serializable()) {
xpc::Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
return false;
}
return sct->WriteStructuredClone(aWriter);
}
}
if (NS_IsMainThread() && xpc::IsReflector(obj)) {
nsCOMPtr<nsISupports> base = xpc::UnwrapReflectorToISupports(obj);
nsCOMPtr<nsIPrincipal> principal = do_QueryInterface(base);

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

@ -70,7 +70,9 @@ enum StructuredCloneTags {
// Adding to the end of the list would make removing of other tags harder in
// future.
SCTAG_DOM_MAX
SCTAG_DOM_MAX,
SCTAG_DOM_STRUCTURED_CLONE_TESTER
};
} // namespace dom

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

@ -0,0 +1,121 @@
/* -*- 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 "StructuredCloneTester.h"
#include "js/StructuredClone.h"
#include "mozilla/RefPtr.h"
#include "mozilla/dom/StructuredCloneTags.h"
#include "mozilla/dom/StructuredCloneTesterBinding.h"
#include "xpcpublic.h"
namespace mozilla {
class ErrorResult;
namespace dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(StructuredCloneTester)
NS_IMPL_CYCLE_COLLECTING_ADDREF(StructuredCloneTester)
NS_IMPL_CYCLE_COLLECTING_RELEASE(StructuredCloneTester)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(StructuredCloneTester)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
StructuredCloneTester::StructuredCloneTester(nsISupports* aParent,
const bool aSerializable,
const bool aDeserializable)
: mParent(aParent),
mSerializable(aSerializable),
mDeserializable(aDeserializable)
{
}
/* static */ already_AddRefed<StructuredCloneTester>
StructuredCloneTester::Constructor(const GlobalObject& aGlobal,
const bool aSerializable,
const bool aDeserializable,
ErrorResult& aRv)
{
RefPtr<StructuredCloneTester> sct = new StructuredCloneTester(aGlobal.GetAsSupports(),
aSerializable,
aDeserializable);
return sct.forget();
}
bool
StructuredCloneTester::Serializable() const
{
return mSerializable;
}
bool
StructuredCloneTester::Deserializable() const
{
return mDeserializable;
}
/* static */ JSObject*
StructuredCloneTester::ReadStructuredClone(JSContext* aCx,
JSStructuredCloneReader* aReader)
{
uint32_t serializable = 0;
uint32_t deserializable = 0;
if (!JS_ReadUint32Pair(aReader, &serializable, &deserializable)) {
return nullptr;
}
nsIGlobalObject* global = xpc::CurrentNativeGlobal(aCx);
if (NS_WARN_IF(!global)) {
return nullptr;
}
// Prevent the return value from being trashed by a GC during ~nsRefPtr
JS::RootedObject result(aCx);
RefPtr<StructuredCloneTester> sct = new StructuredCloneTester(
global,
static_cast<bool>(serializable),
static_cast<bool>(deserializable)
);
// "Fail" deserialization
if (!sct->Deserializable()) {
xpc::Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
return nullptr;
}
result = sct->WrapObject(aCx, nullptr);
return result;
}
bool
StructuredCloneTester::WriteStructuredClone(JSStructuredCloneWriter* aWriter) const
{
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_STRUCTURED_CLONE_TESTER, 0) &&
JS_WriteUint32Pair(aWriter, static_cast<uint32_t>(Serializable()),
static_cast<uint32_t>(Deserializable()));
}
nsISupports*
StructuredCloneTester::GetParentObject() const
{
return mParent;
}
JSObject*
StructuredCloneTester::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
return StructuredCloneTester_Binding::Wrap(aCx, this, aGivenProto);
}
} // namespace dom
} // namespace mozilla

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

@ -0,0 +1,70 @@
/* -*- 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_StructuredCloneTester_h
#define mozilla_dom_StructuredCloneTester_h
#include "mozilla/AlreadyAddRefed.h"
#include "nsCOMPtr.h"
#include "nsISupports.h"
#include "nsWrapperCache.h"
struct JSStructuredCloneReader;
struct JSStructuredCloneWriter;
namespace mozilla {
class ErrorResult;
namespace dom {
class GlobalObject;
class StructuredCloneTester final : public nsISupports
, public nsWrapperCache
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(StructuredCloneTester)
static already_AddRefed<StructuredCloneTester>
Constructor(const GlobalObject& aGlobal, const bool aSerializable,
const bool aDeserializable, ErrorResult& aRv);
bool
Serializable() const;
bool
Deserializable() const;
static JSObject*
ReadStructuredClone(JSContext* aCx, JSStructuredCloneReader* aReader);
bool
WriteStructuredClone(JSStructuredCloneWriter* aWriter) const;
nsISupports*
GetParentObject() const;
// nsWrapperCache interface
JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
private:
StructuredCloneTester(nsISupports* aParent,
const bool aSerializable,
const bool aDeserializable);
~StructuredCloneTester() = default;
nsCOMPtr<nsISupports> mParent;
bool mSerializable;
bool mDeserializable;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_StructuredCloneTester_h

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

@ -220,6 +220,7 @@ EXPORTS.mozilla.dom += [
'StructuredCloneBlob.h',
'StructuredCloneHolder.h',
'StructuredCloneTags.h',
'StructuredCloneTester.h',
'StyleSheetList.h',
'SubtleCrypto.h',
'SyncMessageSender.h',
@ -375,6 +376,7 @@ UNIFIED_SOURCES += [
'ShadowRoot.cpp',
'StructuredCloneBlob.cpp',
'StructuredCloneHolder.cpp',
'StructuredCloneTester.cpp',
'StyleSheetList.cpp',
'SubtleCrypto.cpp',
'TabGroup.cpp',

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

@ -0,0 +1,15 @@
/* -*- 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/.
*/
// The WebIDL compiler does not accept a Pref-ed interface exposed to any scopes
// other than *only* `Window`, so the Func is Pref-ed instead.
[Constructor(boolean serializable, boolean deserializable),
Exposed=(Window,Worker),
Func="mozilla::dom::DOMPrefs::dom_testing_structuredclonetester_enabled"]
interface StructuredCloneTester {
readonly attribute boolean serializable;
readonly attribute boolean deserializable;
};

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

@ -777,6 +777,7 @@ WEBIDL_FILES = [
'StorageType.webidl',
'StreamFilter.webidl',
'StreamFilterDataEvent.webidl',
'StructuredCloneTester.webidl',
'StyleSheet.webidl',
'StyleSheetList.webidl',
'SubtleCrypto.webidl',

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

@ -286,6 +286,12 @@ VARCACHE_PREF(
RelaxedAtomicBool, false
)
VARCACHE_PREF(
"dom.testing.structuredclonetester.enabled",
dom_testing_structuredclonetester_enabled,
RelaxedAtomicBool, false
)
// Enable Storage API for all platforms except Android.
#if !defined(MOZ_WIDGET_ANDROID)
# define PREF_VALUE true