diff --git a/ipc/glue/IPCMessageUtils.h b/ipc/glue/IPCMessageUtils.h index cf2e686b30f7..3597e9ac155e 100644 --- a/ipc/glue/IPCMessageUtils.h +++ b/ipc/glue/IPCMessageUtils.h @@ -44,7 +44,12 @@ #include "prtypes.h" #include "nsStringGlue.h" #include "nsTArray.h" +#include "gfx3DMatrix.h" +#include "gfxColor.h" #include "gfxMatrix.h" +#include "gfxPattern.h" +#include "nsRect.h" +#include "nsRegion.h" #ifdef _MSC_VER #pragma warning( disable : 4800 ) @@ -53,6 +58,8 @@ namespace mozilla { +typedef gfxPattern::GraphicsFilter GraphicsFilterType; + // XXX there are out of place and might be generally useful. Could // move to nscore.h or something. struct void_t { @@ -250,6 +257,7 @@ struct ParamTraits > return false; } + aResult->SetCapacity(length); for (PRUint32 index = 0; index < length; index++) { E* element = aResult->AppendElement(); if (!(element && ReadParam(aMsg, aIter, element))) { @@ -331,6 +339,98 @@ struct ParamTraits } }; +template<> +struct ParamTraits +{ + typedef gfx3DMatrix paramType; + + static void Write(Message* msg, const paramType& param) + { +#define Wr(_f) WriteParam(msg, param. _f) + Wr(_11); Wr(_12); Wr(_13); Wr(_14); + Wr(_21); Wr(_22); Wr(_23); Wr(_24); + Wr(_31); Wr(_32); Wr(_33); Wr(_34); + Wr(_41); Wr(_42); Wr(_43); Wr(_44); +#undef Wr + } + + static bool Read(const Message* msg, void** iter, paramType* result) + { +#define Rd(_f) ReadParam(msg, iter, &result-> _f) + return (Rd(_11) && Rd(_12) && Rd(_13) && Rd(_14) && + Rd(_21) && Rd(_22) && Rd(_23) && Rd(_24) && + Rd(_31) && Rd(_32) && Rd(_33) && Rd(_34) && + Rd(_41) && Rd(_42) && Rd(_43) && Rd(_44)); +#undef Rd + } +}; + + template<> +struct ParamTraits +{ + typedef mozilla::GraphicsFilterType paramType; + + static void Write(Message* msg, const paramType& param) + { + switch (param) { + case gfxPattern::FILTER_FAST: + case gfxPattern::FILTER_GOOD: + case gfxPattern::FILTER_BEST: + case gfxPattern::FILTER_NEAREST: + case gfxPattern::FILTER_BILINEAR: + case gfxPattern::FILTER_GAUSSIAN: + WriteParam(msg, int32(param)); + return; + + default: + NS_RUNTIMEABORT("not reached"); + return; + } + } + + static bool Read(const Message* msg, void** iter, paramType* result) + { + int32 filter; + if (!ReadParam(msg, iter, &filter)) + return false; + + switch (filter) { + case gfxPattern::FILTER_FAST: + case gfxPattern::FILTER_GOOD: + case gfxPattern::FILTER_BEST: + case gfxPattern::FILTER_NEAREST: + case gfxPattern::FILTER_BILINEAR: + case gfxPattern::FILTER_GAUSSIAN: + *result = paramType(filter); + return true; + + default: + return false; + } + } +}; +template<> +struct ParamTraits +{ + typedef gfxRGBA paramType; + + static void Write(Message* msg, const paramType& param) + { + WriteParam(msg, param.r); + WriteParam(msg, param.g); + WriteParam(msg, param.b); + WriteParam(msg, param.a); + } + + static bool Read(const Message* msg, void** iter, paramType* result) + { + return (ReadParam(msg, iter, &result->r) && + ReadParam(msg, iter, &result->g) && + ReadParam(msg, iter, &result->b) && + ReadParam(msg, iter, &result->a)); + } +}; + template<> struct ParamTraits { @@ -357,6 +457,91 @@ struct ParamTraits } }; +template<> +struct ParamTraits +{ + typedef nsIntPoint paramType; + + static void Write(Message* msg, const paramType& param) + { + WriteParam(msg, param.x); + WriteParam(msg, param.y); + } + + static bool Read(const Message* msg, void** iter, paramType* result) + { + return (ReadParam(msg, iter, &result->x) && + ReadParam(msg, iter, &result->y)); + } +}; + +template<> +struct ParamTraits +{ + typedef nsIntRect paramType; + + static void Write(Message* msg, const paramType& param) + { + WriteParam(msg, param.x); + WriteParam(msg, param.y); + WriteParam(msg, param.width); + WriteParam(msg, param.height); + } + + static bool Read(const Message* msg, void** iter, paramType* result) + { + return (ReadParam(msg, iter, &result->x) && + ReadParam(msg, iter, &result->y) && + ReadParam(msg, iter, &result->width) && + ReadParam(msg, iter, &result->height)); + } +}; + +template<> +struct ParamTraits +{ + typedef nsIntRegion paramType; + + static void Write(Message* msg, const paramType& param) + { + nsIntRegionRectIterator it(param); + while (const nsIntRect* r = it.Next()) + WriteParam(msg, *r); + // empty rects are sentinel values because nsRegions will never + // contain them + WriteParam(msg, nsIntRect()); + } + + static bool Read(const Message* msg, void** iter, paramType* result) + { + nsIntRect rect; + while (ReadParam(msg, iter, &rect)) { + if (rect.IsEmpty()) + return true; + result->Or(*result, rect); + } + return false; + } +}; + +template<> +struct ParamTraits +{ + typedef nsIntSize paramType; + + static void Write(Message* msg, const paramType& param) + { + WriteParam(msg, param.width); + WriteParam(msg, param.height); + } + + static bool Read(const Message* msg, void** iter, paramType* result) + { + return (ReadParam(msg, iter, &result->width) && + ReadParam(msg, iter, &result->height)); + } +}; + } /* namespace IPC */ #endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */ diff --git a/ipc/ipdl/test/cxx/IPDLUnitTestProcessChild.cpp b/ipc/ipdl/test/cxx/IPDLUnitTestProcessChild.cpp index a3210fefa13c..01e3c8fe2eb5 100644 --- a/ipc/ipdl/test/cxx/IPDLUnitTestProcessChild.cpp +++ b/ipc/ipdl/test/cxx/IPDLUnitTestProcessChild.cpp @@ -36,6 +36,8 @@ * * ***** END LICENSE BLOCK ***** */ +#include "nsRegion.h" + #include "mozilla/ipc/IOThreadChild.h" #include "IPDLUnitTestProcessChild.h" @@ -52,6 +54,10 @@ IPDLUnitTestProcessChild::Init() IPDLUnitTestChildInit(IOThreadChild::channel(), ParentHandle(), IOThreadChild::message_loop()); + + if (NS_FAILED(nsRegion::InitStatic())) + return false; + return true; } diff --git a/ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp b/ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp index 317925b459b8..eeb75614893a 100644 --- a/ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp +++ b/ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp @@ -10,6 +10,8 @@ #include "base/command_line.h" #include "base/string_util.h" +#include "nsRegion.h" + #include "IPDLUnitTestSubprocess.h" //----------------------------------------------------------------------------- @@ -130,6 +132,9 @@ IPDLUnitTestMain(void* aData) } gIPDLUnitTestName = testString; + if (NS_FAILED(nsRegion::InitStatic())) + fail("initializing nsRegion"); + printf(MOZ_IPDL_TESTINFO_LABEL "| running test | %s\n", gIPDLUnitTestName); std::vector testCaseArgs; diff --git a/ipc/ipdl/test/cxx/PTestDataStructures.ipdl b/ipc/ipdl/test/cxx/PTestDataStructures.ipdl index 5fa590c819f4..f2d53d075021 100644 --- a/ipc/ipdl/test/cxx/PTestDataStructures.ipdl +++ b/ipc/ipdl/test/cxx/PTestDataStructures.ipdl @@ -1,6 +1,7 @@ include protocol PTestDataStructuresSub; using mozilla::null_t; +using nsIntRegion; namespace mozilla { namespace _foo { @@ -177,6 +178,11 @@ parent: sync Test17(Op[] ops); + // test that the ParamTraits::Read() workaround for + // nsTArray's incorrect memmove() semantics works properly + // (nsIntRegion isn't memmove()able) + sync Test18(nsIntRegion[] ops); + state START: send Start goto TEST1; @@ -196,7 +202,8 @@ state TEST13: recv Test13 goto TEST14; state TEST14: recv Test14 goto TEST15; state TEST15: recv Test15 goto TEST16; state TEST16: recv Test16 goto TEST17; -state TEST17: recv Test17 goto DEAD; +state TEST17: recv Test17 goto TEST18; +state TEST18: recv Test18 goto DEAD; state DEAD: recv __delete__; diff --git a/ipc/ipdl/test/cxx/TestDataStructures.cpp b/ipc/ipdl/test/cxx/TestDataStructures.cpp index cacb2953d74b..a3335e671981 100644 --- a/ipc/ipdl/test/cxx/TestDataStructures.cpp +++ b/ipc/ipdl/test/cxx/TestDataStructures.cpp @@ -1,7 +1,11 @@ +#include "mozilla/unused.h" + #include "TestDataStructures.h" #include "IPDLUnitTests.h" // fail etc. +typedef nsTArray RegionArray; + namespace mozilla { namespace _ipdltest { @@ -424,6 +428,19 @@ bool TestDataStructuresParent::RecvTest17(const nsTArray& sa) return true; } +bool TestDataStructuresParent::RecvTest18(const RegionArray& ra) +{ + for (RegionArray::index_type i = 0; i < ra.Length(); ++i) { + nsIntRegionRectIterator it(ra[i]); + // if |ra| has been realloc()d and given a different allocator + // chunk, this next line will nondeterministically crash or + // iloop + while (const nsIntRect* sr = it.Next()) unused << sr; + } + + return true; +} + //----------------------------------------------------------------------------- // child @@ -459,6 +476,7 @@ TestDataStructuresChild::RecvStart() Test15(); Test16(); Test17(); + Test18(); for (uint32 i = 0; i < nactors; ++i) if (!PTestDataStructuresSubChild::Send__delete__(mKids[i])) @@ -897,5 +915,27 @@ TestDataStructuresChild::Test17() printf(" passed %s\n", __FUNCTION__); } +void +TestDataStructuresChild::Test18() +{ + const int nelements = 1000; + RegionArray ra; + // big enough to hopefully force a realloc to a different chunk of + // memory on the receiving side, if the workaround isn't working + // correctly. But SetCapacity() here because we don't want to + // crash on the sending side. + ra.SetCapacity(nelements); + for (int i = 0; i < nelements; ++i) { + nsIntRegion r; + r = r.Or(nsIntRect(0, 0, 10, 10), nsIntRect(10, 10, 10, 10)); + ra.AppendElement(r); + } + + if (!SendTest18(ra)) + fail("sending Test18"); + + printf(" passed %s\n", __FUNCTION__); +} + } // namespace _ipdltest } // namespace mozilla diff --git a/ipc/ipdl/test/cxx/TestDataStructures.h b/ipc/ipdl/test/cxx/TestDataStructures.h index 3809d86ced59..6dffccb01e86 100644 --- a/ipc/ipdl/test/cxx/TestDataStructures.h +++ b/ipc/ipdl/test/cxx/TestDataStructures.h @@ -158,6 +158,9 @@ protected: NS_OVERRIDE virtual bool RecvTest17(const nsTArray& sa); + NS_OVERRIDE + virtual bool RecvTest18(const nsTArray& ra); + NS_OVERRIDE virtual void ActorDestroy(ActorDestroyReason why) { @@ -224,6 +227,7 @@ private: void Test15(); void Test16(); void Test17(); + void Test18(); nsTArray mKids; };